| 1 | package protocol |
| 2 | |
| 3 | import "sort" |
| 4 | |
| 5 | type Direction string |
| 6 | |
| 7 | const ( |
| 8 | // DirectionHostToExtensionRequest is a Host → Extension request; the |
| 9 | // extension answers with the registered result DTO. |
| 10 | DirectionHostToExtensionRequest Direction = "host_to_extension_request" |
| 11 | // DirectionExtensionToHostRequest is an Extension → Host request; the |
| 12 | // host answers with the registered result DTO. |
| 13 | DirectionExtensionToHostRequest Direction = "extension_to_host_request" |
| 14 | // DirectionHostToExtensionNotification is a fire-and-forget Host → |
| 15 | // Extension notification. |
| 16 | DirectionHostToExtensionNotification Direction = "host_to_extension_notification" |
| 17 | // DirectionExtensionToHostNotification is a fire-and-forget Extension → |
| 18 | // Host notification (provider stream chunks). |
| 19 | DirectionExtensionToHostNotification Direction = "extension_to_host_notification" |
| 20 | ) |
| 21 | |
| 22 | // IsNotification reports whether the direction carries no response. |
| 23 | func (d Direction) IsNotification() bool { |
| 24 | return d == DirectionHostToExtensionNotification || d == DirectionExtensionToHostNotification |
| 25 | } |
| 26 | |
| 27 | type OperationClass string |
| 28 | |
| 29 | const ( |
| 30 | ClassLifecycle OperationClass = "lifecycle" |
| 31 | ClassIntercept OperationClass = "intercept" |
| 32 | ClassObservation OperationClass = "observation" |
| 33 | ClassProvider OperationClass = "provider" |
| 34 | ClassUI OperationClass = "ui" |
| 35 | ClassContent OperationClass = "content" |
| 36 | ) |
| 37 | |
| 38 | // InterceptEvent names one of the 17 frozen kernel hook points an extension |
| 39 | // may intercept (extension/intercept) or observe (extension/event). The |
| 40 | // string values mirror internal/extension.InterceptorPoint exactly; they are |
| 41 | // frozen here so the public wire contract does not depend on kernel |
| 42 | // internals. |
| 43 | type InterceptEvent string |
| 44 | |
| 45 | const ( |
| 46 | EventSessionStart InterceptEvent = "session.start" |
| 47 | EventSessionEnd InterceptEvent = "session.end" |
| 48 | EventSessionLoad InterceptEvent = "session.load" |
| 49 | EventSessionSave InterceptEvent = "session.save" |
| 50 | EventSessionRotate InterceptEvent = "session.rotate" |
| 51 | EventInputReceive InterceptEvent = "input.receive" |
| 52 | EventAgentBeforeStart InterceptEvent = "agent.before_start" |
| 53 | EventSystemPromptBuild InterceptEvent = "system_prompt.build" |
| 54 | EventContextPrepare InterceptEvent = "context.prepare" |
| 55 | EventProviderRequest InterceptEvent = "provider.request" |
| 56 | EventProviderResponse InterceptEvent = "provider.response" |
| 57 | EventToolBefore InterceptEvent = "tool.before" |
| 58 | EventToolAfter InterceptEvent = "tool.after" |
| 59 | EventPermissionDecision InterceptEvent = "permission.decision" |
| 60 | EventCompactionPrepare InterceptEvent = "compaction.prepare" |
| 61 | EventCompactionComplete InterceptEvent = "compaction.complete" |
| 62 | EventFrontendEvent InterceptEvent = "frontend.event" |
| 63 | ) |
| 64 | |
| 65 | // InterceptEvents returns the 17 frozen hook point names, sorted. Adding an |
| 66 | // event is a conscious protocol change: the count is pinned by tests and the |
| 67 | // list is frozen into the generated schema document. |
| 68 | func InterceptEvents() []string { |
| 69 | out := []string{ |
| 70 | string(EventSessionStart), string(EventSessionEnd), string(EventSessionLoad), |
| 71 | string(EventSessionSave), string(EventSessionRotate), string(EventInputReceive), |
| 72 | string(EventAgentBeforeStart), string(EventSystemPromptBuild), string(EventContextPrepare), |
| 73 | string(EventProviderRequest), string(EventProviderResponse), string(EventToolBefore), |
| 74 | string(EventToolAfter), string(EventPermissionDecision), string(EventCompactionPrepare), |
| 75 | string(EventCompactionComplete), string(EventFrontendEvent), |
| 76 | } |
| 77 | sort.Strings(out) |
| 78 | return out |
| 79 | } |
| 80 | |
| 81 | // InterceptDecision is the extension's ruling on an intercepted event. |
| 82 | type InterceptDecision string |
| 83 | |
| 84 | const ( |
| 85 | DecisionContinue InterceptDecision = "continue" |
| 86 | DecisionBlock InterceptDecision = "block" |
| 87 | DecisionReplace InterceptDecision = "replace" |
| 88 | DecisionAllow InterceptDecision = "allow" |
| 89 | DecisionDeny InterceptDecision = "deny" |
| 90 | ) |
| 91 | |
| 92 | // UIHostKind identifies which host UI surface family renders extension UI. |
| 93 | type UIHostKind string |
| 94 | |
| 95 | const ( |
| 96 | UIHostTUI UIHostKind = "tui" |
| 97 | UIHostDesktop UIHostKind = "desktop" |
| 98 | UIHostACP UIHostKind = "acp" |
| 99 | UIHostHeadless UIHostKind = "headless" |
| 100 | ) |
| 101 | |
| 102 | // UISurfaceKind is the kind of structured surface an extension publishes. |
| 103 | type UISurfaceKind string |
| 104 | |
| 105 | const ( |
| 106 | UISurfaceStatus UISurfaceKind = "status" |
| 107 | UISurfaceCard UISurfaceKind = "card" |
| 108 | UISurfaceForm UISurfaceKind = "form" |
| 109 | UISurfaceNotification UISurfaceKind = "notification" |
| 110 | ) |
| 111 | |
| 112 | // UIRequestKind is the kind of blocking UI prompt the host shows on an |
| 113 | // extension's behalf. |
| 114 | type UIRequestKind string |
| 115 | |
| 116 | const ( |
| 117 | UIRequestConfirm UIRequestKind = "confirm" |
| 118 | UIRequestInput UIRequestKind = "input" |
| 119 | UIRequestSelect UIRequestKind = "select" |
| 120 | UIRequestMultiselect UIRequestKind = "multiselect" |
| 121 | ) |
| 122 | |
| 123 | // UIFieldKind is the input kind of one form field. Values mirror |
| 124 | // UIRequestKind deliberately: a form composes the same primitive prompts. |
| 125 | type UIFieldKind string |
| 126 | |
| 127 | const ( |
| 128 | UIFieldConfirm UIFieldKind = "confirm" |
| 129 | UIFieldInput UIFieldKind = "input" |
| 130 | UIFieldSelect UIFieldKind = "select" |
| 131 | UIFieldMultiselect UIFieldKind = "multiselect" |
| 132 | ) |
| 133 | |
| 134 | // UISeverity grades status and notification payloads. |
| 135 | type UISeverity string |
| 136 | |
| 137 | const ( |
| 138 | UISeverityInfo UISeverity = "info" |
| 139 | UISeverityWarn UISeverity = "warn" |
| 140 | UISeverityError UISeverity = "error" |
| 141 | ) |
| 142 | |
| 143 | // ProviderRole mirrors the provider message roles without importing |
| 144 | // internal/provider into the public wire schema. |
| 145 | type ProviderRole string |
| 146 | |
| 147 | const ( |
| 148 | ProviderRoleSystem ProviderRole = "system" |
| 149 | ProviderRoleUser ProviderRole = "user" |
| 150 | ProviderRoleAssistant ProviderRole = "assistant" |
| 151 | ProviderRoleTool ProviderRole = "tool" |
| 152 | ) |
| 153 | |
| 154 | // ProviderChunkType classifies one provider stream chunk. |
| 155 | type ProviderChunkType string |
| 156 | |
| 157 | const ( |
| 158 | ChunkText ProviderChunkType = "text" |
| 159 | ChunkReasoning ProviderChunkType = "reasoning" |
| 160 | ChunkToolCallStart ProviderChunkType = "tool_call_start" |
| 161 | ChunkToolCallDelta ProviderChunkType = "tool_call_args_delta" |
| 162 | ChunkToolCall ProviderChunkType = "tool_call" |
| 163 | ChunkUsage ProviderChunkType = "usage" |
| 164 | ChunkDone ProviderChunkType = "done" |
| 165 | ChunkError ProviderChunkType = "error" |
| 166 | ) |
| 167 | |
| 168 | // ProviderErrorCode classifies redacted provider stream failures. Raw |
| 169 | // provider errors may contain credentials or endpoints and never cross the |
| 170 | // wire; only these codes and generic messages do. |
| 171 | type ProviderErrorCode string |
| 172 | |
| 173 | const ( |
| 174 | ProviderFailed ProviderErrorCode = "provider_failed" |
| 175 | ProviderInterrupted ProviderErrorCode = "provider_interrupted" |
| 176 | ) |
| 177 | |
| 178 | // ContentEncoding names the canonical text encoding of content ref data. |
| 179 | type ContentEncoding string |
| 180 | |
| 181 | const ContentUTF8 ContentEncoding = "utf8" |
| 182 |