Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ update-proto-submodule:

NEXUS_SCHEMA_ROOT := $(PROTO_ROOT)/nexus
NEXUS_PROTO_OUT := workflowservice/v1/workflowservicenexus
NEXUS_WIT_OUT := workflowservice/v1/systemnexus

@dplyukhin dplyukhin Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does anyone have opinions on where we should put the WIT files?


##### Compile proto files for go #####
grpc: http-api-docs go-grpc copy-helpers nexus-gen
grpc: http-api-docs go-grpc copy-helpers nexus-gen system-nexus

nexus-gen:
printf $(COLOR) "Generate nexus service definitions..."
Expand All @@ -55,6 +56,13 @@ nexus-gen:
--out-file $(CURDIR)/$(NEXUS_PROTO_OUT)/service_nexus.pb.go \
temporal-proto-models-nexusrpc.yaml

.PHONY: system-nexus
system-nexus:
printf $(COLOR) "Update system-nexus WIT files..."
rm -rf $(NEXUS_WIT_OUT)
mkdir -p $(NEXUS_WIT_OUT)
cp -R $(NEXUS_SCHEMA_ROOT)/workflow-service.wit $(NEXUS_SCHEMA_ROOT)/deps $(NEXUS_WIT_OUT)/
Comment on lines +59 to +64

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tconley1428 Based on your plans for future WIT stuff, does this make sense for how to lay things out in the api-go directory? i.e., we copy XXX-service.wit into the XXXservice/v1/systemnexus directory, along with the entirety of deps/?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really have any opinion on location here.


# Only install helpers when their source has changed
HELPER_FILES = $(shell find ./cmd/protoc-gen-go-helpers)
.go-helpers-installed: $(HELPER_FILES)
Expand Down
170 changes: 170 additions & 0 deletions workflowservice/v1/systemnexus/deps/nexus-temporal-types/model.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package nexus:temporal-types@1.0.0;

interface model {
/// String-shaped placeholder for semantic types that generators reinterpret.
type placeholder = string;

/// @nexus.proto "temporal.api.common.v1.Payload" typescript-import="@temporalio/proto"
/// @nexus.type
/// python="typing.Any"
/// typescript="common.Payload"
/// dotnet="object?"
/// dotnet-to="ProtoExtensions.ToPayload"
/// typescript-import="@temporalio/common"
type payload = placeholder;

/// @nexus.proto "temporal.api.common.v1.Payloads"
/// typescript-import="@temporalio/proto"
/// @nexus.type dotnet="IReadOnlyCollection<object?>" dotnet-to="ProtoExtensions.ToPayloads"
type payloads = list<payload>;

/// Callable result annotation for workflow functions.
/// @nexus.type
/// python="collections.abc.Awaitable[WorkflowResult]"
/// typescript="Promise<any>"
/// dotnet="System.Threading.Tasks.Task<object?>"
type workflow-result = placeholder;

/// Receiver/context argument for workflow callable method forms.
/// @nexus.type python="typing.Any" typescript="any" dotnet="object"
type callable-prefix = placeholder;

/// @nexus.function-args
/// varargs=true
/// param="args"
/// typescript-drop-prefix=true
workflow-call: async func(callable-prefix: callable-prefix, args: payloads) -> workflow-result;

/// Callable result annotation for signal functions.
/// @nexus.type python="None | collections.abc.Awaitable[None]" typescript="void" dotnet="void"
type signal-result = placeholder;

/// @nexus.function-args
/// varargs=true
/// param="signal-args"
/// typescript-drop-prefix=true
signal-call: func(callable-prefix: callable-prefix, signal-args: payloads) -> signal-result;

/// @nexus.proto "temporal.api.common.v1.WorkflowType" typescript-import="@temporalio/proto"
/// @nexus.type
/// python="str"
/// typescript="string"
/// dotnet="string"
/// dotnet-to="ProtoExtensions.ToWorkflowTypeProto"
type workflow-type = placeholder;

/// @nexus.function
/// primary=true
/// signature="workflow-call"
/// args-field="input"
/// result-type-parameter="WorkflowResult"
/// alternate-type="workflow-type"
/// dotnet-name-extractor="TemporalFunctionNames.WorkflowName"
/// dotnet-call-extractor="TemporalFunctionNames.ExtractCall"
/// @nexus.add-rpc-compatible-with "workflow-type"
type workflow-function = placeholder;

/// @nexus.function
/// signature="signal-call"
/// args-field="signal-input"
/// alternate-type="string"
/// python-converter="signal_function_to_proto"
/// typescript-name-extractor="signalFunctionName"
/// dotnet-name-extractor="TemporalFunctionNames.SignalName"
/// dotnet-call-extractor="TemporalFunctionNames.ExtractCall"
/// typescript-value-type="workflow.SignalDefinition<any[]>"
/// typescript-args-type="Value extends workflow.SignalDefinition<infer Args, any> ? Args : never"
/// typescript-import="@temporalio/workflow"
/// @nexus.add-rpc-compatible-with "string"
type signal-function = placeholder;

/// @nexus.proto "temporal.api.common.v1.RetryPolicy" typescript-import="@temporalio/proto"
/// @nexus.type
/// python="temporalio.common.RetryPolicy"
/// typescript="common.RetryPolicy"
/// dotnet="Temporalio.Common.RetryPolicy"
/// typescript-import="@temporalio/common"
type retry-policy = placeholder;

/// @nexus.proto "temporal.api.taskqueue.v1.TaskQueue" typescript-import="@temporalio/proto"
/// @nexus.type
/// python="str"
/// typescript="string"
/// dotnet="string"
/// dotnet-to="ProtoExtensions.ToTaskQueueProto"
type task-queue = placeholder;

/// @nexus.proto "temporal.api.common.v1.Memo" typescript-import="@temporalio/proto"
/// @nexus.type python="collections.abc.Mapping[str, typing.Any]" typescript="Record<string, unknown>" dotnet="IReadOnlyDictionary<string, object?>"
type memo = placeholder;

/// @nexus.proto "temporal.api.common.v1.SearchAttributes" typescript-import="@temporalio/proto"
/// @nexus.type
/// python="temporalio.common.TypedSearchAttributes"
/// typescript="common.TypedSearchAttributes"
/// dotnet="Temporalio.Common.SearchAttributeCollection"
/// typescript-import="@temporalio/common"
type search-attributes = placeholder;

/// @nexus.proto "temporal.api.common.v1.Priority" typescript-import="@temporalio/proto"
/// @nexus.type
/// python="temporalio.common.Priority"
/// typescript="common.Priority"
/// dotnet="Temporalio.Common.Priority"
/// typescript-import="@temporalio/common"
type priority = placeholder;

/// @nexus.proto "temporal.api.workflow.v1.VersioningOverride" typescript-import="@temporalio/proto"
/// @nexus.type
/// python="temporalio.common.VersioningOverride"
/// typescript="common.VersioningOverride"
/// dotnet="Temporalio.Common.VersioningOverride"
/// typescript-import="@temporalio/common"
type versioning-override = placeholder;

/// @nexus.proto "google.protobuf.Duration" typescript-import="@temporalio/proto"
/// @nexus.type
/// python="datetime.timedelta"
/// typescript="common.Duration"
/// dotnet="System.TimeSpan"
/// typescript-import="@temporalio/common"
type duration = placeholder;

/// @nexus.proto "temporal.api.enums.v1.WorkflowIdReusePolicy" typescript-import="@temporalio/proto"
/// @nexus.type
/// python="temporalio.common.WorkflowIDReusePolicy"
/// typescript="common.WorkflowIdReusePolicy"
/// dotnet="Temporalio.Api.Enums.V1.WorkflowIdReusePolicy"
/// typescript-import="@temporalio/common"
enum workflow-id-reuse-policy {
allow-duplicate,
allow-duplicate-failed-only,
reject-duplicate,
terminate-if-running,
}

/// @nexus.proto "temporal.api.enums.v1.WorkflowIdConflictPolicy" typescript-import="@temporalio/proto"
/// @nexus.type
/// python="temporalio.common.WorkflowIDConflictPolicy"
/// typescript="common.WorkflowIdConflictPolicy"
/// dotnet="Temporalio.Api.Enums.V1.WorkflowIdConflictPolicy"
/// typescript-import="@temporalio/common"
enum workflow-id-conflict-policy {
fail,
use-existing,
terminate-existing,
}

/// @nexus.proto "temporal.api.sdk.v1.UserMetadata" typescript-import="@temporalio/proto"
/// @nexus.flatten-in-api
record user-metadata {
/// @nexus.doc "Single-line fixed summary for the workflow execution that may appear in UI and CLI. This can be in single-line Temporal Markdown format."
/// @nexus.proto-field "summary"
/// @nexus.flattened-type python="str" typescript="string" dotnet="string"
static-summary: option<payload>,
/// @nexus.doc "General fixed details for the workflow execution that may appear in UI and CLI. This can be in Temporal Markdown format and can span multiple lines. This value is fixed on the workflow execution and cannot be updated."
/// @nexus.proto-field "details"
/// @nexus.flattened-type python="str" typescript="string" dotnet="string"
static-details: option<payload>,
}
}
126 changes: 126 additions & 0 deletions workflowservice/v1/systemnexus/workflow-service.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
package temporal:nexus@1.0.0;

world system {
export workflow-service;
}

/// @nexus.endpoint "__temporal_system"
/// @nexus.service-name "temporal.api.workflowservice.v1.WorkflowService"
/// @nexus.namespace dotnet="Temporalio.Workflows"
/// @nexus.operations-class dotnet="Workflow"
/// @nexus.delay-load-temporalio-workflow
/// @nexus.experimental
interface workflow-service {
use nexus:temporal-types/model@1.0.0.{
duration,
memo,
payloads,
placeholder,
priority,
retry-policy,
search-attributes,
signal-function,
task-queue,
user-metadata,
versioning-override,
workflow-function,
workflow-id-conflict-policy,
workflow-id-reuse-policy,
};

/// @nexus.doc "Request fields for signaling a workflow, starting it first if needed."
/// @nexus.experimental
/// @nexus.proto "temporal.api.workflowservice.v1.SignalWithStartWorkflowExecutionRequest" typescript-import="@temporalio/proto"
record signal-with-start-workflow-request {
/// @nexus.doc
/// python="Workflow type name or callable identifying the workflow to start."
/// typescript="Workflow type name or workflow function identifying the workflow to start."
/// dotnet="Workflow type name or workflow expression identifying the workflow to start."
/// @nexus.proto-field "workflow_type"
workflow: workflow-function,
/// @nexus.doc "Unique identifier for the workflow execution."
/// @nexus.proto-field "workflow_id"
id: string,
/// @nexus.doc "Task queue to run the workflow on."
task-queue: task-queue,
/// @nexus.doc
/// python="Signal name or callable to send with the start request."
/// typescript="Signal name or signal definition to send with the start request."
/// dotnet="Signal name or signal expression to send with the start request."
/// @nexus.proto-field "signal_name"
signal: signal-function,
/// @nexus.doc "Total workflow execution timeout, including retries and continue-as-new."
/// @nexus.proto-field "workflow_execution_timeout"
execution-timeout: option<duration>,
/// @nexus.doc "Timeout of a single workflow run."
/// @nexus.proto-field "workflow_run_timeout"
run-timeout: option<duration>,
/// @nexus.doc "Timeout of a single workflow task."
/// @nexus.proto-field "workflow_task_timeout"
task-timeout: option<duration>,
/// @nexus.omit
identity: placeholder,
/// @nexus.doc "Request ID used to deduplicate workflow start requests."
request-id: option<string>,
/// @nexus.doc "Behavior when a closed workflow with the same ID exists. Default is allow-duplicate."
/// @nexus.proto-field "workflow_id_reuse_policy"
/// @nexus.default "allow-duplicate"
id-reuse-policy: workflow-id-reuse-policy,
/// @nexus.doc "Behavior when a workflow is currently running with the same ID. Set to use-existing for idempotent deduplication on workflow ID. Cannot be set if id-reuse-policy is terminate-if-running."
/// @nexus.proto-field "workflow_id_conflict_policy"
id-conflict-policy: option<workflow-id-conflict-policy>,
/// @nexus.doc "Retry policy for the workflow."
retry-policy: option<retry-policy>,
/// @nexus.doc "Cron schedule for recurring workflow executions. See https://docs.temporal.io/cron-job."
cron-schedule: option<string>,
/// @nexus.doc "Memo for the workflow."
memo: option<memo>,
/// @nexus.doc "Typed search attributes for the workflow."
search-attributes: option<search-attributes>,
/// @nexus.doc "Priority of the workflow execution."
priority: option<priority>,
/// @nexus.doc "Override for workflow versioning behavior."
versioning-override: option<versioning-override>,
/// @nexus.doc "Amount of time to wait before starting the workflow. This does not work with cron-schedule."
/// @nexus.proto-field "workflow_start_delay"
start-delay: option<duration>,
user-metadata: option<user-metadata>,
/// @nexus.source python="workflow_namespace" typescript="workflowNamespace" dotnet="TemporalWorkflowContext.WorkflowNamespace"
namespace: string,
/// @nexus.omit
control: placeholder,
/// @nexus.omit
header: placeholder,
/// @nexus.omit
links: placeholder,
/// @nexus.omit
time-skipping-config: placeholder,
}

/// @nexus.experimental
/// @nexus.proto "temporal.api.workflowservice.v1.SignalWithStartWorkflowExecutionResponse" typescript-import="@temporalio/proto"
record signal-with-start-workflow-response {
run-id: option<string>,
started: option<bool>,
/// @nexus.omit
signal-link: placeholder,
first-execution-run-id: string,
}

/// @nexus.doc
/// "Signal a workflow, starting it first if needed."
/// returns="A workflow handle to the started workflow."
/// @nexus.output-transform
/// python-type="temporalio.workflow.ExternalWorkflowHandle[WorkflowResult]"
/// python="temporalio.workflow.get_external_workflow_handle(request.id, run_id=result.run_id)"
/// typescript-type="workflow.ExternalWorkflowHandle"
/// typescript="workflow.getExternalWorkflowHandle(request.id, result.runId ?? undefined)"
/// typescript-import="@temporalio/workflow"
/// dotnet-type="Temporalio.Workflows.ExternalWorkflowHandle"
/// dotnet="Temporalio.Workflows.Workflow.GetExternalWorkflowHandle(request.Id, result.RunId)"
/// @nexus.operation name="SignalWithStartWorkflowExecution"
/// @nexus.experimental
signal-with-start-workflow: func(
request: signal-with-start-workflow-request,
) -> signal-with-start-workflow-response;
}
Loading