diff --git a/Makefile b/Makefile index 2c2e12c81..e3eccd631 100644 --- a/Makefile +++ b/Makefile @@ -115,6 +115,7 @@ install/dev: go install honnef.co/go/tools/cmd/staticcheck@v0.4.6 go install mvdan.cc/gofumpt@v0.6.0 go install github.com/icholy/gomajor@v0.9.5 + go install github.com/stateful/go-proto-gql/protoc-gen-gql@latest .PHONY: install/goreleaser install/goreleaser: diff --git a/buf.gen.yaml b/buf.gen.yaml index 62299bc68..f5912f360 100644 --- a/buf.gen.yaml +++ b/buf.gen.yaml @@ -1,16 +1,20 @@ -version: v1 +version: v2 plugins: # Remote plugin. You can switch to a local one by using "go". - - plugin: buf.build/protocolbuffers/go + - remote: buf.build/protocolbuffers/go out: pkg/api/gen/proto/go opt: paths=source_relative # Remote plugin. You can switch to a local one by using "go-grpc". - - plugin: buf.build/grpc/go + - remote: buf.build/grpc/go out: pkg/api/gen/proto/go opt: paths=source_relative # Remote plugin. You can switch to a local one by using "timostamm-protobuf-ts". - - plugin: buf.build/community/timostamm-protobuf-ts + - remote: buf.build/community/timostamm-protobuf-ts out: pkg/api/gen/proto/ts opt: output_javascript,optimize_code_size,long_type_string,add_pb_suffix,ts_nocheck,eslint_disable + + # Local plugin to generate GQL schema + - local: protoc-gen-gql + out: pkg/api/gen/proto/gql diff --git a/pkg/api/gen/proto/gql/runme/ai/v1alpha1/ai.graphql b/pkg/api/gen/proto/gql/runme/ai/v1alpha1/ai.graphql new file mode 100644 index 000000000..2ca4a7c8c --- /dev/null +++ b/pkg/api/gen/proto/gql/runme/ai/v1alpha1/ai.graphql @@ -0,0 +1,230 @@ +""" + The AIService service is used to provide assistant capabilities to Runme. + +""" +directive @AIService on FIELD_DEFINITION +""" + Wrapper message for `bool`. + + The JSON representation for `BoolValue` is JSON `true` and `false`. + +""" +type BoolValue { + """ + The bool value. + + """ + value: Boolean +} +""" + Wrapper message for `bool`. + + The JSON representation for `BoolValue` is JSON `true` and `false`. + +""" +input BoolValueInput { + """ + The bool value. + + """ + value: Boolean +} +scalar Bytes +type Cell { + kind: CellKind + value: String + languageId: String + metadata: [Cell_MetadataEntry!] + textRange: TextRange + outputs: [CellOutput!] + executionSummary: CellExecutionSummary +} +type CellExecutionSummary { + executionOrder: UInt32Value + success: BoolValue + timing: ExecutionSummaryTiming +} +input CellExecutionSummaryInput { + executionOrder: UInt32ValueInput + success: BoolValueInput + timing: ExecutionSummaryTimingInput +} +input CellInput { + kind: CellKind + value: String + languageId: String + metadata: [Cell_MetadataEntryInput!] + textRange: TextRangeInput + outputs: [CellOutputInput!] + executionSummary: CellExecutionSummaryInput +} +enum CellKind { + CELL_KIND_UNSPECIFIED + CELL_KIND_MARKUP + CELL_KIND_CODE +} +type CellOutput { + items: [CellOutputItem!] + metadata: [CellOutput_MetadataEntry!] + processInfo: CellOutputProcessInfo +} +input CellOutputInput { + items: [CellOutputItemInput!] + metadata: [CellOutput_MetadataEntryInput!] + processInfo: CellOutputProcessInfoInput +} +type CellOutputItem { + data: Bytes + type: String + mime: String +} +input CellOutputItemInput { + data: Bytes + type: String + mime: String +} +type CellOutputProcessInfo { + exitReason: ProcessInfoExitReason + pid: Int64Value +} +input CellOutputProcessInfoInput { + exitReason: ProcessInfoExitReasonInput + pid: Int64ValueInput +} +type CellOutput_MetadataEntry { + key: String + value: String +} +input CellOutput_MetadataEntryInput { + key: String + value: String +} +type Cell_MetadataEntry { + key: String + value: String +} +input Cell_MetadataEntryInput { + key: String + value: String +} +type ExecutionSummaryTiming { + startTime: Int64Value + endTime: Int64Value +} +input ExecutionSummaryTimingInput { + startTime: Int64ValueInput + endTime: Int64ValueInput +} +input FrontmatterInput { + shell: String + cwd: String + skipPrompts: Boolean + runme: FrontmatterRunmeInput + category: String + terminalRows: String +} +input FrontmatterRunmeInput { + id: String + version: String + session: RunmeSessionInput +} +input GenerateCellsRequestInput { + notebook: NotebookInput +} +type GenerateCellsResponse { + cells: [Cell!] +} +""" + Wrapper message for `int64`. + + The JSON representation for `Int64Value` is JSON string. + +""" +type Int64Value { + """ + The int64 value. + + """ + value: Int +} +""" + Wrapper message for `int64`. + + The JSON representation for `Int64Value` is JSON string. + +""" +input Int64ValueInput { + """ + The int64 value. + + """ + value: Int +} +type Mutation { + """ + GenerateCells uses the AI to generate cells to insert into the notebook. + + """ + aIServiceGenerateCells(in: GenerateCellsRequestInput): GenerateCellsResponse +} +input NotebookInput { + cells: [CellInput!] + metadata: [Notebook_MetadataEntryInput!] + frontmatter: FrontmatterInput +} +input Notebook_MetadataEntryInput { + key: String + value: String +} +type ProcessInfoExitReason { + type: String + code: UInt32Value +} +input ProcessInfoExitReasonInput { + type: String + code: UInt32ValueInput +} +type Query { + dummy: Boolean +} +input RunmeSessionDocumentInput { + relativePath: String +} +input RunmeSessionInput { + id: String + document: RunmeSessionDocumentInput +} +type TextRange { + start: Int + end: Int +} +input TextRangeInput { + start: Int + end: Int +} +""" + Wrapper message for `uint32`. + + The JSON representation for `UInt32Value` is JSON number. + +""" +type UInt32Value { + """ + The uint32 value. + + """ + value: Int +} +""" + Wrapper message for `uint32`. + + The JSON representation for `UInt32Value` is JSON number. + +""" +input UInt32ValueInput { + """ + The uint32 value. + + """ + value: Int +} diff --git a/pkg/api/gen/proto/gql/runme/config/v1alpha1/config.graphql b/pkg/api/gen/proto/gql/runme/config/v1alpha1/config.graphql new file mode 100644 index 000000000..6c768dd22 --- /dev/null +++ b/pkg/api/gen/proto/gql/runme/config/v1alpha1/config.graphql @@ -0,0 +1,3 @@ +type Query { + dummy: Boolean +} diff --git a/pkg/api/gen/proto/gql/runme/parser/v1/parser.graphql b/pkg/api/gen/proto/gql/runme/parser/v1/parser.graphql new file mode 100644 index 000000000..4bd09da1c --- /dev/null +++ b/pkg/api/gen/proto/gql/runme/parser/v1/parser.graphql @@ -0,0 +1,281 @@ +directive @ParserService on FIELD_DEFINITION +""" + Wrapper message for `bool`. + + The JSON representation for `BoolValue` is JSON `true` and `false`. + +""" +type BoolValue { + """ + The bool value. + + """ + value: Boolean +} +""" + Wrapper message for `bool`. + + The JSON representation for `BoolValue` is JSON `true` and `false`. + +""" +input BoolValueInput { + """ + The bool value. + + """ + value: Boolean +} +scalar Bytes +type Cell { + kind: CellKind + value: String + languageId: String + metadata: [Cell_MetadataEntry!] + textRange: TextRange + outputs: [CellOutput!] + executionSummary: CellExecutionSummary +} +type CellExecutionSummary { + executionOrder: UInt32Value + success: BoolValue + timing: ExecutionSummaryTiming +} +input CellExecutionSummaryInput { + executionOrder: UInt32ValueInput + success: BoolValueInput + timing: ExecutionSummaryTimingInput +} +input CellInput { + kind: CellKind + value: String + languageId: String + metadata: [Cell_MetadataEntryInput!] + textRange: TextRangeInput + outputs: [CellOutputInput!] + executionSummary: CellExecutionSummaryInput +} +enum CellKind { + CELL_KIND_UNSPECIFIED + CELL_KIND_MARKUP + CELL_KIND_CODE +} +type CellOutput { + items: [CellOutputItem!] + metadata: [CellOutput_MetadataEntry!] + processInfo: CellOutputProcessInfo +} +input CellOutputInput { + items: [CellOutputItemInput!] + metadata: [CellOutput_MetadataEntryInput!] + processInfo: CellOutputProcessInfoInput +} +type CellOutputItem { + data: Bytes + type: String + mime: String +} +input CellOutputItemInput { + data: Bytes + type: String + mime: String +} +type CellOutputProcessInfo { + exitReason: ProcessInfoExitReason + pid: Int64Value +} +input CellOutputProcessInfoInput { + exitReason: ProcessInfoExitReasonInput + pid: Int64ValueInput +} +type CellOutput_MetadataEntry { + key: String + value: String +} +input CellOutput_MetadataEntryInput { + key: String + value: String +} +type Cell_MetadataEntry { + key: String + value: String +} +input Cell_MetadataEntryInput { + key: String + value: String +} +input DeserializeRequestInput { + source: Bytes + options: DeserializeRequestOptionsInput +} +input DeserializeRequestOptionsInput { + identity: RunmeIdentity +} +type DeserializeResponse { + notebook: Notebook +} +type ExecutionSummaryTiming { + startTime: Int64Value + endTime: Int64Value +} +input ExecutionSummaryTimingInput { + startTime: Int64ValueInput + endTime: Int64ValueInput +} +type Frontmatter { + shell: String + cwd: String + skipPrompts: Boolean + runme: FrontmatterRunme + category: String + terminalRows: String +} +input FrontmatterInput { + shell: String + cwd: String + skipPrompts: Boolean + runme: FrontmatterRunmeInput + category: String + terminalRows: String +} +type FrontmatterRunme { + id: String + version: String + session: RunmeSession +} +input FrontmatterRunmeInput { + id: String + version: String + session: RunmeSessionInput +} +""" + Wrapper message for `int64`. + + The JSON representation for `Int64Value` is JSON string. + +""" +type Int64Value { + """ + The int64 value. + + """ + value: Int +} +""" + Wrapper message for `int64`. + + The JSON representation for `Int64Value` is JSON string. + +""" +input Int64ValueInput { + """ + The int64 value. + + """ + value: Int +} +type Mutation { + parserServiceDeserialize(in: DeserializeRequestInput): DeserializeResponse + parserServiceSerialize(in: SerializeRequestInput): SerializeResponse +} +type Notebook { + cells: [Cell!] + metadata: [Notebook_MetadataEntry!] + frontmatter: Frontmatter +} +input NotebookInput { + cells: [CellInput!] + metadata: [Notebook_MetadataEntryInput!] + frontmatter: FrontmatterInput +} +type Notebook_MetadataEntry { + key: String + value: String +} +input Notebook_MetadataEntryInput { + key: String + value: String +} +type ProcessInfoExitReason { + type: String + code: UInt32Value +} +input ProcessInfoExitReasonInput { + type: String + code: UInt32ValueInput +} +type Query { + dummy: Boolean +} +enum RunmeIdentity { + """ + aka NONE + + """ + RUNME_IDENTITY_UNSPECIFIED + RUNME_IDENTITY_ALL + RUNME_IDENTITY_DOCUMENT + RUNME_IDENTITY_CELL +} +type RunmeSession { + id: String + document: RunmeSessionDocument +} +type RunmeSessionDocument { + relativePath: String +} +input RunmeSessionDocumentInput { + relativePath: String +} +input RunmeSessionInput { + id: String + document: RunmeSessionDocumentInput +} +input SerializeRequestInput { + notebook: NotebookInput + options: SerializeRequestOptionsInput +} +input SerializeRequestOptionsInput { + outputs: SerializeRequestOutputOptionsInput + session: RunmeSessionInput +} +input SerializeRequestOutputOptionsInput { + enabled: Boolean + summary: Boolean +} +type SerializeResponse { + result: Bytes +} +type TextRange { + start: Int + end: Int +} +input TextRangeInput { + start: Int + end: Int +} +""" + Wrapper message for `uint32`. + + The JSON representation for `UInt32Value` is JSON number. + +""" +type UInt32Value { + """ + The uint32 value. + + """ + value: Int +} +""" + Wrapper message for `uint32`. + + The JSON representation for `UInt32Value` is JSON number. + +""" +input UInt32ValueInput { + """ + The uint32 value. + + """ + value: Int +} diff --git a/pkg/api/gen/proto/gql/runme/project/v1/project.graphql b/pkg/api/gen/proto/gql/runme/project/v1/project.graphql new file mode 100644 index 000000000..9966c7541 --- /dev/null +++ b/pkg/api/gen/proto/gql/runme/project/v1/project.graphql @@ -0,0 +1,116 @@ +directive @LoadRequestKind on INPUT_FIELD_DEFINITION +directive @ProjectService on FIELD_DEFINITION +input DirectoryProjectOptionsInput { + """ + Path to a directory containing the project. + + """ + path: String + """ + If true, .gitignore file is ignored, as well as .git/info/exclude. + + """ + skipGitignore: Boolean + """ + A list of file patterns, compatible with .gitignore syntax, + to ignore. + + """ + ignoreFilePatterns: [String!] + """ + If true, it disables lookuping up for .git folder + in the parent directories. + + """ + skipRepoLookupUpward: Boolean +} +input FileProjectOptionsInput { + path: String +} +type LoadEventError { + errorMessage: String +} +type LoadEventFinishedParsingDoc { + path: String +} +type LoadEventFoundDir { + path: String +} +type LoadEventFoundFile { + path: String +} +type LoadEventFoundTask { + documentPath: String + id: String + name: String + isNameGenerated: Boolean +} +type LoadEventStartedParsingDoc { + path: String +} +enum LoadEventType { + LOAD_EVENT_TYPE_UNSPECIFIED + LOAD_EVENT_TYPE_STARTED_WALK + LOAD_EVENT_TYPE_FOUND_DIR + LOAD_EVENT_TYPE_FOUND_FILE + LOAD_EVENT_TYPE_FINISHED_WALK + LOAD_EVENT_TYPE_STARTED_PARSING_DOC + LOAD_EVENT_TYPE_FINISHED_PARSING_DOC + LOAD_EVENT_TYPE_FOUND_TASK + LOAD_EVENT_TYPE_ERROR +} +input LoadRequestInput { + directory: DirectoryProjectOptionsInput @LoadRequestKind + file: FileProjectOptionsInput @LoadRequestKind + identity: RunmeIdentity +} +type LoadResponse { + type: LoadEventType + data: LoadResponseData +} +union LoadResponseData = LoadResponse_StartedWalk | LoadResponse_FoundDir | LoadResponse_FoundFile | LoadResponse_FinishedWalk | LoadResponse_StartedParsingDoc | LoadResponse_FinishedParsingDoc | LoadResponse_FoundTask | LoadResponse_Error +type LoadResponse_Error { + error: LoadEventError +} +type LoadResponse_FinishedParsingDoc { + finishedParsingDoc: LoadEventFinishedParsingDoc +} +type LoadResponse_FinishedWalk { + finishedWalk: LoadEventFinishedWalk +} +type LoadResponse_FoundDir { + foundDir: LoadEventFoundDir +} +type LoadResponse_FoundFile { + foundFile: LoadEventFoundFile +} +type LoadResponse_FoundTask { + foundTask: LoadEventFoundTask +} +type LoadResponse_StartedParsingDoc { + startedParsingDoc: LoadEventStartedParsingDoc +} +type LoadResponse_StartedWalk { + startedWalk: LoadEventStartedWalk +} +type Query { + dummy: Boolean +} +enum RunmeIdentity { + """ + aka NONE + + """ + RUNME_IDENTITY_UNSPECIFIED + RUNME_IDENTITY_ALL + RUNME_IDENTITY_DOCUMENT + RUNME_IDENTITY_CELL +} +type Subscription { + """ + Load creates a new project, walks it, and streams events + about found directories, files, and code blocks. + + """ + projectServiceLoad(in: LoadRequestInput): LoadResponse +} diff --git a/pkg/api/gen/proto/gql/runme/runner/v1/runner.graphql b/pkg/api/gen/proto/gql/runme/runner/v1/runner.graphql new file mode 100644 index 000000000..f8408919e --- /dev/null +++ b/pkg/api/gen/proto/gql/runme/runner/v1/runner.graphql @@ -0,0 +1,567 @@ +""" + use script for unnormalized cell content + whereas commands is for normalized shell commands + +""" +directive @ResolveProgramRequestSource on INPUT_FIELD_DEFINITION +directive @RunnerService on FIELD_DEFINITION +scalar Bytes +enum CommandMode { + COMMAND_MODE_UNSPECIFIED + COMMAND_MODE_INLINE_SHELL + COMMAND_MODE_TEMP_FILE + COMMAND_MODE_TERMINAL +} +input CreateSessionRequestInput { + """ + metadata is a map of client specific metadata. + + """ + metadata: [CreateSessionRequest_MetadataEntryInput!] + """ + envs field provides an initial set of environment variables + for a newly created session. + + """ + envs: [String!] + """ + optional project from which to immediately load environment variables + + """ + project: ProjectInput + """ + optional selection of which env store implementation to sue + + """ + envStoreType: SessionEnvStoreType +} +input CreateSessionRequest_MetadataEntryInput { + key: String + value: String +} +type CreateSessionResponse { + session: Session +} +input DeleteSessionRequestInput { + id: String +} +input ExecuteRequestInput { + """ + program_name is a name of the program to execute. + If it's not a path (relative or absolute), the runner + will try to resolve the name. + For example: "sh", "/bin/bash". + + """ + programName: String + """ + arguments is a list of arguments passed to the program. + + """ + arguments: [String!] + """ + directory to execute the program in. + + """ + directory: String + """ + envs is a list of additional environment variables + that will be injected to the executed program. + + """ + envs: [String!] + """ + commands are commands to be executed by the program. + The commands are joined and executed as a script. + For example: "echo 'Hello, World'", "ls -l /etc". + This is mutually exclusive with the script field. + + """ + commands: [String!] + """ + script is code to be executed by the program. + Individual lines are joined with the new line character. + This is mutually exclusive with the commands field. + + """ + script: String + """ + tty when true allocates a pseudo-TTY. + + """ + tty: Boolean + """ + input_data is a byte array that will be send as input + to the program. + + """ + inputData: Bytes + """ + stop requests the running process to be stopped. + It is allowed only in the consecutive calls. + + """ + stop: ExecuteStop + """ + sets pty winsize + has no effect in non-interactive mode + + """ + winsize: WinsizeInput + """ + background indicates a background process + this will send the process' PID as a first response + + """ + background: Boolean + """ + session_id indicates in which Session the program should execute. + Executing in a Session might provide additional context like + environment variables. + + """ + sessionId: String + """ + strategy for selecting session + + """ + sessionStrategy: SessionStrategy + """ + project for this runner + used to load environment variables from .env files + + """ + project: ProjectInput + """ + whether to store the stdout of the last ran + block in the environment variable `__` + + """ + storeLastOutput: Boolean + commandMode: CommandMode + """ + language id associated with script + + """ + languageId: String + """ + file extension associated with script + + """ + fileExtension: String + """ + optional well known id for cell/block. "know" meaning that + CLI/notebook UX have id/name for cells/blocks that contain commands. + While the runner doesn't require the name to work, it is useful for + auxiliary concerns (e.g. tracing, logging, etc). + + """ + knownId: String + """ + optional well known name for cell/block. "know" meaning that + CLI/notebook UX have id/name for cells/blocks that contain commands. + While the runner doesn't require the name to work, it is useful for + auxiliary concerns (e.g. tracing, logging, etc). + + """ + knownName: String +} +type ExecuteResponse { + """ + exit_code is sent only in the final message. + + """ + exitCode: UInt32Value + """ + stdout_data contains bytes from stdout since the last response. + + """ + stdoutData: Bytes + """ + stderr_data contains bytes from stderr since the last response. + + """ + stderrData: Bytes + """ + pid contains the process' PID + this is only sent once in an initial response for background processes. + + """ + pid: ProcessPID + """ + mime_type is a detected MIME type of the stdout_data. + + This is only sent once in the first response containing stdout_data. + + """ + mimeType: String +} +enum ExecuteStop { + EXECUTE_STOP_UNSPECIFIED + EXECUTE_STOP_INTERRUPT + EXECUTE_STOP_KILL +} +input GetSessionRequestInput { + id: String +} +type GetSessionResponse { + session: Session +} +type ListSessionsResponse { + sessions: [Session!] +} +input MonitorEnvStoreRequestInput { + session: SessionInput +} +type MonitorEnvStoreResponse { + type: MonitorEnvStoreType + data: MonitorEnvStoreResponseData +} +union MonitorEnvStoreResponseData = MonitorEnvStoreResponse_Snapshot +type MonitorEnvStoreResponseSnapshot { + envs: [MonitorEnvStoreResponseSnapshot_SnapshotEnv!] +} +type MonitorEnvStoreResponseSnapshot_Error { + code: Int + message: String +} +type MonitorEnvStoreResponseSnapshot_SnapshotEnv { + status: MonitorEnvStoreResponseSnapshot_Status + name: String + spec: String + origin: String + originalValue: String + resolvedValue: String + createTime: String + updateTime: String + errors: [MonitorEnvStoreResponseSnapshot_Error!] +} +enum MonitorEnvStoreResponseSnapshot_Status { + STATUS_UNSPECIFIED + STATUS_LITERAL + STATUS_HIDDEN + STATUS_MASKED +} +type MonitorEnvStoreResponse_Snapshot { + snapshot: MonitorEnvStoreResponseSnapshot +} +enum MonitorEnvStoreType { + MONITOR_ENV_STORE_TYPE_UNSPECIFIED + """ + possible expansion to have a "timeline" view + MONITOR_ENV_STORE_TYPE_TIMELINE = 2; + + """ + MONITOR_ENV_STORE_TYPE_SNAPSHOT +} +type Mutation { + runnerServiceCreateSession(in: CreateSessionRequestInput): CreateSessionResponse + runnerServiceGetSession(in: GetSessionRequestInput): GetSessionResponse + runnerServiceListSessions: ListSessionsResponse + runnerServiceDeleteSession(in: DeleteSessionRequestInput): Boolean + """ + Execute executes a program. Examine "ExecuteRequest" to explore + configuration options. + + It's a bidirectional stream RPC method. It expects the first + "ExecuteRequest" to contain details of a program to execute. + Subsequent "ExecuteRequest" should only contain "input_data" as + other fields will be ignored. + + """ + runnerServiceExecute(in: ExecuteRequestInput): ExecuteResponse + """ + ResolveProgram resolves variables from a script or a list of commands + using the provided sources, which can be a list of environment variables, + a session, or a project. + For now, the resolved variables are only the exported ones using `export`. + + """ + runnerServiceResolveProgram(in: ResolveProgramRequestInput): ResolveProgramResponse +} +type ProcessPID { + pid: Int +} +input ProjectInput { + """ + project root folder + + """ + root: String + """ + list of environment files to try and load + start with + + """ + envLoadOrder: [String!] +} +type Query { + dummy: Boolean +} +type ResolveProgramCommandList { + """ + commands are commands to be executed by the program. + The commands are joined and executed as a script. + For example: ["echo 'Hello, World'", "ls -l /etc"]. + + """ + lines: [String!] +} +input ResolveProgramCommandListInput { + """ + commands are commands to be executed by the program. + The commands are joined and executed as a script. + For example: ["echo 'Hello, World'", "ls -l /etc"]. + + """ + lines: [String!] +} +input ResolveProgramRequestInput { + """ + commands are commands to be executed by the program. + The commands are joined and executed as a script. + + """ + commands: ResolveProgramCommandListInput @ResolveProgramRequestSource + """ + script is code to be executed by the program. + Individual lines are joined with the new line character. + + """ + script: String @ResolveProgramRequestSource + """ + mode determines how variables resolution occurs. + It is usually based on document or cell annotation config. + + """ + mode: ResolveProgramRequest_Mode + """ + env is a list of explicit environment variables that will be used + to resolve the environment variables found in the source. + + """ + env: [String!] + """ + session_id indicates which session is the source of + environment variables. If not provided, the most recent + session can be used using session_strategy. + + """ + sessionId: String + """ + session_strategy is a strategy for selecting the session. + + """ + sessionStrategy: SessionStrategy + """ + project used to load environment variables from .env files. + + """ + project: ProjectInput +} +enum ResolveProgramRequest_Mode { + """ + unspecified is auto (default) which prompts for all + unresolved environment variables. + Subsequent runs will likely resolve via the session. + + """ + MODE_UNSPECIFIED + """ + prompt always means to prompt for all environment variables. + + """ + MODE_PROMPT_ALL + """ + skip means to not prompt for any environment variables. + All variables will be marked as resolved. + + """ + MODE_SKIP_ALL +} +type ResolveProgramResponse { + script: String + """ + use script until commands normalization is implemented + + """ + commands: ResolveProgramCommandList + vars: [ResolveProgramResponse_VarResult!] +} +enum ResolveProgramResponse_Status { + """ + unspecified is the default value and it means unresolved. + + """ + STATUS_UNSPECIFIED + """ + unresolved with message means that the variable is unresolved + but it contains a message. E.g. FOO=this is message + + """ + STATUS_UNRESOLVED_WITH_MESSAGE + """ + unresolved with placeholder means that the variable is unresolved + but it contains a placeholder. E.g. FOO="this is placeholder" + + """ + STATUS_UNRESOLVED_WITH_PLACEHOLDER + """ + resolved means that the variable is resolved. + + """ + STATUS_RESOLVED + """ + unresolved with secret means that the variable is unresolved + and it requires treatment as a secret. + + """ + STATUS_UNRESOLVED_WITH_SECRET +} +type ResolveProgramResponse_VarResult { + """ + prompt indicates the resolution status of the env variable. + + """ + status: ResolveProgramResponse_Status + """ + name is the name of the environment variable. + + """ + name: String + """ + original_value is a default value of the environment variable. + It might be a value that is assigned to the variable in the script, + like FOO=bar or FOO=${FOO:-bar}. + If the variable is not assigned, it is an empty string. + + """ + originalValue: String + """ + resolved_value is a value of the environment variable resolved from a source. + If it is an empty string, it means that the environment variable is not resolved. + + """ + resolvedValue: String +} +type Session { + id: String + """ + envs keeps track of session environment variables. + They can be modified by executing programs which + alter them through "export" and "unset" commands. + + """ + envs: [String!] + """ + metadata is a map of client specific metadata. + + """ + metadata: [Session_MetadataEntry!] +} +""" + env store implementation + +""" +enum SessionEnvStoreType { + """ + uses default env store + + """ + SESSION_ENV_STORE_TYPE_UNSPECIFIED + """ + uses owl store + + """ + SESSION_ENV_STORE_TYPE_OWL +} +input SessionInput { + id: String + """ + envs keeps track of session environment variables. + They can be modified by executing programs which + alter them through "export" and "unset" commands. + + """ + envs: [String!] + """ + metadata is a map of client specific metadata. + + """ + metadata: [Session_MetadataEntryInput!] +} +""" + strategy for selecting a session in an initial execute request + +""" +enum SessionStrategy { + """ + uses session_id field to determine session + if none is present, a new session is created + + """ + SESSION_STRATEGY_UNSPECIFIED + """ + uses most recently used session on the grpc server + if there is none, a new one is created + + """ + SESSION_STRATEGY_MOST_RECENT +} +type Session_MetadataEntry { + key: String + value: String +} +input Session_MetadataEntryInput { + key: String + value: String +} +type Subscription { + runnerServiceMonitorEnvStore(in: MonitorEnvStoreRequestInput): MonitorEnvStoreResponse + """ + Execute executes a program. Examine "ExecuteRequest" to explore + configuration options. + + It's a bidirectional stream RPC method. It expects the first + "ExecuteRequest" to contain details of a program to execute. + Subsequent "ExecuteRequest" should only contain "input_data" as + other fields will be ignored. + + """ + runnerServiceExecute(in: ExecuteRequestInput): ExecuteResponse +} +""" + Wrapper message for `uint32`. + + The JSON representation for `UInt32Value` is JSON number. + +""" +type UInt32Value { + """ + The uint32 value. + + """ + value: Int +} +input WinsizeInput { + """ + number of rows (in cells) + + """ + rows: Int + """ + number of columns (in cells) + + """ + cols: Int + """ + width in pixels + + """ + x: Int + """ + height in pixels + + """ + y: Int +} diff --git a/pkg/api/gen/proto/gql/runme/runner/v2alpha1/config.graphql b/pkg/api/gen/proto/gql/runme/runner/v2alpha1/config.graphql new file mode 100644 index 000000000..6c768dd22 --- /dev/null +++ b/pkg/api/gen/proto/gql/runme/runner/v2alpha1/config.graphql @@ -0,0 +1,3 @@ +type Query { + dummy: Boolean +} diff --git a/pkg/api/gen/proto/gql/runme/runner/v2alpha1/runner.graphql b/pkg/api/gen/proto/gql/runme/runner/v2alpha1/runner.graphql new file mode 100644 index 000000000..869e3e18f --- /dev/null +++ b/pkg/api/gen/proto/gql/runme/runner/v2alpha1/runner.graphql @@ -0,0 +1,600 @@ +directive @ProgramConfigSource on INPUT_FIELD_DEFINITION +""" + use script for unnormalized cell content + whereas commands is for normalized shell commands + +""" +directive @ResolveProgramRequestSource on INPUT_FIELD_DEFINITION +directive @RunnerService on FIELD_DEFINITION +scalar Bytes +enum CommandMode { + COMMAND_MODE_UNSPECIFIED + COMMAND_MODE_INLINE + COMMAND_MODE_FILE + COMMAND_MODE_TERMINAL + COMMAND_MODE_CLI +} +input CreateSessionRequestInput { + """ + metadata is a map of client specific metadata. + + """ + metadata: [CreateSessionRequest_MetadataEntryInput!] + """ + env field provides an initial set of environment variables + for a newly created session. + + """ + env: [String!] + """ + project from which to load environment variables. + They will be appended to the list from the env field. + The env field has a higher priority. + + """ + project: ProjectInput + """ + optional selection of which env store implementation to sue + + """ + envStoreType: SessionEnvStoreType +} +input CreateSessionRequest_MetadataEntryInput { + key: String + value: String +} +type CreateSessionResponse { + session: Session +} +input DeleteSessionRequestInput { + id: String +} +input ExecuteRequestInput { + config: ProgramConfigInput + """ + input_data is a byte array that will be send as input + to the program. + + """ + inputData: Bytes + """ + stop requests the running process to be stopped. + It is allowed only in the consecutive calls. + + """ + stop: ExecuteStop + """ + sets pty winsize + has no effect in non-interactive mode + + """ + winsize: WinsizeInput + """ + session_id indicates in which Session the program should execute. + Executing in a Session might provide additional context like + environment variables. + + """ + sessionId: String + """ + session_strategy is a strategy for selecting the session. + + """ + sessionStrategy: SessionStrategy + """ + project used to load environment variables from .env files. + + """ + project: ProjectInput + """ + store_stdout_in_env, if true, will store the stdout under well known name + and the last ran block in the environment variable `__`. + + """ + storeStdoutInEnv: Boolean +} +type ExecuteResponse { + """ + exit_code is sent only in the final message. + + """ + exitCode: UInt32Value + """ + stdout_data contains bytes from stdout since the last response. + + """ + stdoutData: Bytes + """ + stderr_data contains bytes from stderr since the last response. + + """ + stderrData: Bytes + """ + pid contains the process' PID. + + This is only sent once in an initial response for background processes. + + """ + pid: UInt32Value + """ + mime_type is a detected MIME type of the stdout_data. + + This is only sent once in the first response containing stdout_data. + + """ + mimeType: String +} +enum ExecuteStop { + EXECUTE_STOP_UNSPECIFIED + EXECUTE_STOP_INTERRUPT + EXECUTE_STOP_KILL +} +input GetSessionRequestInput { + id: String +} +type GetSessionResponse { + session: Session +} +type ListSessionsResponse { + sessions: [Session!] +} +input MonitorEnvStoreRequestInput { + session: SessionInput +} +type MonitorEnvStoreResponse { + type: MonitorEnvStoreType + data: MonitorEnvStoreResponseData +} +union MonitorEnvStoreResponseData = MonitorEnvStoreResponse_Snapshot +type MonitorEnvStoreResponseSnapshot { + envs: [MonitorEnvStoreResponseSnapshot_SnapshotEnv!] +} +type MonitorEnvStoreResponseSnapshot_Error { + code: Int + message: String +} +type MonitorEnvStoreResponseSnapshot_SnapshotEnv { + status: MonitorEnvStoreResponseSnapshot_Status + name: String + spec: String + origin: String + originalValue: String + resolvedValue: String + createTime: String + updateTime: String + errors: [MonitorEnvStoreResponseSnapshot_Error!] +} +enum MonitorEnvStoreResponseSnapshot_Status { + STATUS_UNSPECIFIED + STATUS_LITERAL + STATUS_HIDDEN + STATUS_MASKED +} +type MonitorEnvStoreResponse_Snapshot { + snapshot: MonitorEnvStoreResponseSnapshot +} +enum MonitorEnvStoreType { + MONITOR_ENV_STORE_TYPE_UNSPECIFIED + """ + possible expansion to have a "timeline" view + MONITOR_ENV_STORE_TYPE_TIMELINE = 2; + + """ + MONITOR_ENV_STORE_TYPE_SNAPSHOT +} +type Mutation { + runnerServiceCreateSession(in: CreateSessionRequestInput): CreateSessionResponse + runnerServiceGetSession(in: GetSessionRequestInput): GetSessionResponse + runnerServiceListSessions: ListSessionsResponse + runnerServiceUpdateSession(in: UpdateSessionRequestInput): UpdateSessionResponse + runnerServiceDeleteSession(in: DeleteSessionRequestInput): Boolean + """ + Execute executes a program. Examine "ExecuteRequest" to explore + configuration options. + + It's a bidirectional stream RPC method. It expects the first + "ExecuteRequest" to contain details of a program to execute. + Subsequent "ExecuteRequest" should only contain "input_data" as + other fields will be ignored. + + """ + runnerServiceExecute(in: ExecuteRequestInput): ExecuteResponse + """ + ResolveProgram resolves variables from a script or a list of commands + using the provided sources, which can be a list of environment variables, + a session, or a project. + For now, the resolved variables are only the exported ones using `export`. + + """ + runnerServiceResolveProgram(in: ResolveProgramRequestInput): ResolveProgramResponse +} +""" + ProgramConfig is a configuration for a program to execute. + From this configuration, any program can be built. + +""" +input ProgramConfigInput { + """ + program_name is a name of the program to execute. + If it's not a path (relative or absolute), the runner + will try to resolve the name. + For example: "sh", "/bin/bash". + + """ + programName: String + """ + arguments is a list of arguments passed to the program. + + """ + arguments: [String!] + """ + directory to execute the program in. + + """ + directory: String + """ + language_id associated with script to allow interpreter + detection if no specific interpreter program is provided. + + """ + languageId: String + """ + background indicates a background process + required to handle running background tasks via CLI in C/I + + """ + background: Boolean + """ + file_extension associated with script. Some interpreters are strict + about file extensions, such as tsc which requires "ts" extension. + + """ + fileExtension: String + """ + env is a list of additional environment variables + that will be injected to the executed program. + + """ + env: [String!] + """ + commands are commands to be executed by the program. + The commands are joined and executed as a script. + + """ + commands: ProgramConfig_CommandListInput @ProgramConfigSource + """ + script is code to be executed by the program. + Individual lines are joined with the new line character. + + """ + script: String @ProgramConfigSource + """ + interactive, if true, uses a pseudo-tty to execute the program. + Otherwise, the program is executed using in-memory buffers for I/O. + + """ + interactive: Boolean + """ + TODO(adamb): understand motivation for this. In theory, source + should tell whether to execute it inline or as a file. + + """ + mode: CommandMode + """ + optional well known id for cell/block + + """ + knownId: String + """ + optional well known name for cell/block + + """ + knownName: String +} +input ProgramConfig_CommandListInput { + """ + commands are commands to be executed by the program. + The commands are joined and executed as a script. + For example: ["echo 'Hello, World'", "ls -l /etc"]. + + """ + items: [String!] +} +input ProjectInput { + """ + root is a root directory of the project. + The semantic is the same as for the "--project" + flag in "runme". + + """ + root: String + """ + env_load_order is list of environment files + to try and load env from. + + """ + envLoadOrder: [String!] +} +type Query { + dummy: Boolean +} +type ResolveProgramCommandList { + """ + commands are commands to be executed by the program. + The commands are joined and executed as a script. + For example: ["echo 'Hello, World'", "ls -l /etc"]. + + """ + lines: [String!] +} +input ResolveProgramCommandListInput { + """ + commands are commands to be executed by the program. + The commands are joined and executed as a script. + For example: ["echo 'Hello, World'", "ls -l /etc"]. + + """ + lines: [String!] +} +input ResolveProgramRequestInput { + """ + commands are commands to be executed by the program. + The commands are joined and executed as a script. + + """ + commands: ResolveProgramCommandListInput @ResolveProgramRequestSource + """ + script is code to be executed by the program. + Individual lines are joined with the new line character. + + """ + script: String @ResolveProgramRequestSource + """ + mode determines how variables resolution occurs. + It is usually based on document or cell annotation config. + + """ + mode: ResolveProgramRequest_Mode + """ + env is a list of explicit environment variables that will be used + to resolve the environment variables found in the source. + + """ + env: [String!] + """ + session_id indicates which session is the source of + environment variables. If not provided, the most recent + session can be used using session_strategy. + + """ + sessionId: String + """ + session_strategy is a strategy for selecting the session. + + """ + sessionStrategy: SessionStrategy + """ + project used to load environment variables from .env files. + + """ + project: ProjectInput +} +enum ResolveProgramRequest_Mode { + """ + unspecified is auto (default) which prompts for all + unresolved environment variables. + Subsequent runs will likely resolve via the session. + + """ + MODE_UNSPECIFIED + """ + prompt always means to prompt for all environment variables. + + """ + MODE_PROMPT_ALL + """ + skip means to not prompt for any environment variables. + All variables will be marked as resolved. + + """ + MODE_SKIP_ALL +} +type ResolveProgramResponse { + script: String + """ + use script until commands normalization is implemented + + """ + commands: ResolveProgramCommandList + vars: [ResolveProgramResponse_VarResult!] +} +enum ResolveProgramResponse_Status { + """ + unspecified is the default value and it means unresolved. + + """ + STATUS_UNSPECIFIED + """ + resolved means that the variable is resolved. + + """ + STATUS_RESOLVED + """ + unresolved with message means that the variable is unresolved + but it contains a message. E.g. FOO=this is message. + + """ + STATUS_UNRESOLVED_WITH_MESSAGE + """ + unresolved with placeholder means that the variable is unresolved + but it contains a placeholder. E.g. FOO="this is placeholder". + + """ + STATUS_UNRESOLVED_WITH_PLACEHOLDER + """ + unresolved with secret means that the variable is unresolved + and it requires treatment as a secret. + + """ + STATUS_UNRESOLVED_WITH_SECRET +} +type ResolveProgramResponse_VarResult { + """ + prompt indicates the resolution status of the env variable. + + """ + status: ResolveProgramResponse_Status + """ + name is the name of the environment variable. + + """ + name: String + """ + original_value is a default value of the environment variable. + It might be a value that is assigned to the variable in the script, + like FOO=bar or FOO=${FOO:-bar}. + If the variable is not assigned, it is an empty string. + + """ + originalValue: String + """ + resolved_value is a value of the environment variable resolved from a source. + If it is an empty string, it means that the environment variable is not resolved. + + """ + resolvedValue: String +} +type Session { + id: String + """ + env keeps track of session environment variables. + They can be modified by executing programs which + alter them through "export" and "unset" commands. + + """ + env: [String!] + """ + metadata is a map of client specific metadata. + + """ + metadata: [Session_MetadataEntry!] +} +""" + env store implementation + +""" +enum SessionEnvStoreType { + """ + uses default env store + + """ + SESSION_ENV_STORE_TYPE_UNSPECIFIED + """ + uses owl store + + """ + SESSION_ENV_STORE_TYPE_OWL +} +input SessionInput { + id: String + """ + env keeps track of session environment variables. + They can be modified by executing programs which + alter them through "export" and "unset" commands. + + """ + env: [String!] + """ + metadata is a map of client specific metadata. + + """ + metadata: [Session_MetadataEntryInput!] +} +""" + SessionStrategy determines a session selection in + an initial execute request. + +""" +enum SessionStrategy { + """ + Uses the session_id field to determine the session. + If none is present, a new session is created. + + """ + SESSION_STRATEGY_UNSPECIFIED + """ + Uses the most recent session on the server. + If there is none, a new one is created. + + """ + SESSION_STRATEGY_MOST_RECENT +} +type Session_MetadataEntry { + key: String + value: String +} +input Session_MetadataEntryInput { + key: String + value: String +} +type Subscription { + runnerServiceMonitorEnvStore(in: MonitorEnvStoreRequestInput): MonitorEnvStoreResponse + """ + Execute executes a program. Examine "ExecuteRequest" to explore + configuration options. + + It's a bidirectional stream RPC method. It expects the first + "ExecuteRequest" to contain details of a program to execute. + Subsequent "ExecuteRequest" should only contain "input_data" as + other fields will be ignored. + + """ + runnerServiceExecute(in: ExecuteRequestInput): ExecuteResponse +} +""" + Wrapper message for `uint32`. + + The JSON representation for `UInt32Value` is JSON number. + +""" +type UInt32Value { + """ + The uint32 value. + + """ + value: Int +} +input UpdateSessionRequestInput { + id: String + """ + metadata is a map of client specific metadata. + + """ + metadata: [UpdateSessionRequest_MetadataEntryInput!] + """ + env field provides an initial set of environment variables + for a newly created session. + + """ + env: [String!] + """ + project from which to load environment variables. + They will be appended to the list from the env field. + The env field has a higher priority. + + """ + project: ProjectInput +} +input UpdateSessionRequest_MetadataEntryInput { + key: String + value: String +} +type UpdateSessionResponse { + session: Session +} +input WinsizeInput { + rows: Int + cols: Int + x: Int + y: Int +}