@linkshell/wire 0.2.8 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/rpc.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import { goalChangeSchema, sessionGoalSchema } from "./goal.js";
3
+ import { acpAgentSettingsSchema, acpFeaturesSchema, acpRemoteAgentSchema, acpProviderSchema } from "./acp.js";
4
+ import { editorRequestSchema, editorResultSchema } from "./editor.js";
3
5
  import {
4
6
  backgroundTaskSchema,
7
+ agentInfoSchema,
5
8
  gatewayStatusSchema,
6
9
  machineInfoSchema,
7
10
  portInfoSchema,
@@ -13,8 +16,9 @@ import {
13
16
  gitInfoSchema,
14
17
  worktreeEntrySchema,
15
18
  questionAnswerSchema,
19
+ pendingPermissionSchema,
16
20
  } from "./model.js";
17
- import { contentBlockSchema, sessionEventSchema } from "./updates.js";
21
+ import { contentBlockSchema, sessionEventSchema, sessionNoticeSchema } from "./updates.js";
18
22
 
19
23
  // ── JSON-RPC 2.0 framing ─────────────────────────────────────────────
20
24
 
@@ -72,7 +76,36 @@ export const directoryEntrySchema = z.object({
72
76
  });
73
77
  export type DirectoryEntry = z.infer<typeof directoryEntrySchema>;
74
78
 
75
- export const methods = {
79
+ const acpMethods = {
80
+ "agents.editor": { params: editorRequestSchema, result: editorResultSchema },
81
+ "agents.acp": {
82
+ params: z.object({ agent: z.string().min(1), sessionId: z.string().optional() }),
83
+ result: z.object({ features: acpFeaturesSchema, settings: acpAgentSettingsSchema, interactions: z.array(pendingPermissionSchema) }),
84
+ },
85
+ "agents.pending": { params: empty, result: z.object({ interactions: z.array(z.object({ agent: z.string(), request: pendingPermissionSchema })) }) },
86
+ "agents.configure": {
87
+ params: z.object({ agent: z.string().min(1), settings: acpAgentSettingsSchema, sessionId: z.string().optional() }),
88
+ result: empty,
89
+ },
90
+ "agents.authenticate": {
91
+ params: z.object({ agent: z.string().min(1), methodId: z.string().optional(), logout: z.boolean().optional() }),
92
+ result: z.object({ terminalId: z.string().optional() }),
93
+ },
94
+ "agents.respond": {
95
+ params: z.object({ agent: z.string().min(1), requestId: z.string().min(1), optionId: z.string().optional(), answers: z.array(questionAnswerSchema).optional() }),
96
+ result: empty,
97
+ },
98
+ "agents.providers": {
99
+ params: z.object({ agent: z.string().min(1), operation: z.enum(["list", "set", "disable"]), config: z.object({ providerId: z.string(), apiType: z.string().optional(), baseUrl: z.string().url().optional(), headers: z.record(z.string()).optional() }).optional() }),
100
+ result: z.object({ providers: z.array(acpProviderSchema) }),
101
+ },
102
+ "agents.custom": {
103
+ params: z.object({ save: acpRemoteAgentSchema.optional(), remove: z.string().optional() }),
104
+ result: z.object({ agents: z.array(acpRemoteAgentSchema) }),
105
+ },
106
+ } as const;
107
+
108
+ const coreMethods = {
76
109
  "machine.info": {
77
110
  params: empty,
78
111
  result: machineInfoSchema,
@@ -152,6 +185,10 @@ export const methods = {
152
185
  params: z.object({ sessionId: z.string().min(1) }),
153
186
  result: z.object({ subagents: z.array(subagentInfoSchema) }),
154
187
  },
188
+ "sessions.cancelSubagent": {
189
+ params: z.object({ sessionId: z.string().min(1), nativeSessionId: z.string().min(1) }),
190
+ result: empty,
191
+ },
155
192
  /**
156
193
  * One sub-agent's conversation: the call that started it and the events
157
194
  * under it (the latest 2000), oldest first. Later ones arrive on the
@@ -575,6 +612,8 @@ export const methods = {
575
612
  },
576
613
  } as const;
577
614
 
615
+ export const methods: typeof coreMethods & typeof acpMethods = { ...coreMethods, ...acpMethods };
616
+
578
617
  export type MethodName = keyof typeof methods;
579
618
  export type MethodParams<M extends MethodName> = z.input<(typeof methods)[M]["params"]>;
580
619
  export type MethodResult<M extends MethodName> = z.infer<(typeof methods)[M]["result"]>;
@@ -586,6 +625,9 @@ export function isMethodName(name: string): name is MethodName {
586
625
  // ── Notifications (host → client) ────────────────────────────────────
587
626
 
588
627
  export const notifications = {
628
+ "agent.changed": z.object({ agent: agentInfoSchema }),
629
+ "agent.interaction": z.object({ agent: z.string(), request: z.union([pendingPermissionSchema, z.object({ requestId: z.string(), resolved: z.literal(true) })]) }),
630
+ "session.notice": z.object({ sessionId: z.string(), notice: sessionNoticeSchema }),
589
631
  "session.event": sessionEventSchema,
590
632
  /**
591
633
  * Sent before a subscription's backlog when it doesn't continue from the
package/src/updates.ts CHANGED
@@ -2,54 +2,14 @@ import { z } from "zod";
2
2
  import { asyncQuestionSchema } from "./async-questions.js";
3
3
  import { sessionGoalSchema } from "./goal.js";
4
4
  import { backgroundTaskSchema, permissionOptionSchema, questionAnswerSchema, questionSchema, sessionDriverSchema, sessionStateSchema, toolKindSchema } from "./model.js";
5
+ import { contentBlockSchema, toolCallContentSchema, toolCallStatusSchema } from "./content.js";
6
+ export * from "./content.js";
5
7
  import { workflowAgentStateSchema, workflowSchema } from "./workflow.js";
6
8
 
7
9
  // Session updates mirror ACP's `SessionUpdate` shapes (discriminated by
8
10
  // `sessionUpdate`) so one renderer works for every agent. LinkShell-specific
9
11
  // updates use the `ls_` prefix.
10
12
 
11
- export const contentBlockSchema = z.discriminatedUnion("type", [
12
- z.object({ type: z.literal("text"), text: z.string() }),
13
- z.object({
14
- type: z.literal("image"),
15
- mimeType: z.string(),
16
- data: z.string().optional(),
17
- uri: z.string().optional(),
18
- }),
19
- z.object({
20
- type: z.literal("resource_link"),
21
- uri: z.string(),
22
- name: z.string(),
23
- /** What the link names: a file (default), a skill the user invoked, or another agent. */
24
- kind: z.enum(["file", "skill", "agent"]).optional(),
25
- }),
26
- ]);
27
- export type ContentBlock = z.infer<typeof contentBlockSchema>;
28
-
29
- export const toolCallStatusSchema = z.enum(["pending", "in_progress", "completed", "failed"]);
30
- export type ToolCallStatus = z.infer<typeof toolCallStatusSchema>;
31
-
32
- export const toolCallContentSchema = z.discriminatedUnion("type", [
33
- z.object({ type: z.literal("content"), content: contentBlockSchema }),
34
- /** ACP diff: full before/after text. */
35
- z.object({
36
- type: z.literal("diff"),
37
- path: z.string(),
38
- oldText: z.string().nullable().optional(),
39
- newText: z.string(),
40
- }),
41
- /** Unified diff, for agents (Codex) that report patches rather than file text. */
42
- z.object({
43
- type: z.literal("patch"),
44
- path: z.string(),
45
- change: z.enum(["add", "delete", "update"]),
46
- movePath: z.string().optional(),
47
- diff: z.string(),
48
- }),
49
- z.object({ type: z.literal("terminal"), terminalId: z.string() }),
50
- ]);
51
- export type ToolCallContent = z.infer<typeof toolCallContentSchema>;
52
-
53
13
  export const toolCallLocationSchema = z.object({
54
14
  path: z.string(),
55
15
  line: z.number().int().optional(),
@@ -72,6 +32,8 @@ export const toolDetailSchema = z.discriminatedUnion("type", [
72
32
  agentType: z.string().optional(),
73
33
  /** A named agent's address, distinct from its role. */
74
34
  name: z.string().optional(),
35
+ nativeSessionId: z.string().optional(),
36
+ canCancel: z.boolean().optional(),
75
37
  model: z.string().optional(),
76
38
  /** Agent outcome when a tool's coarse completed/failed state is insufficient. */
77
39
  state: workflowAgentStateSchema.optional(),
@@ -95,20 +57,30 @@ export const planEntrySchema = z.object({
95
57
  });
96
58
  export type PlanEntry = z.infer<typeof planEntrySchema>;
97
59
 
98
- export const stopReasonSchema = z.enum(["end_turn", "cancelled", "error", "max_tokens", "refusal"]);
60
+ export const stopReasonSchema = z.enum(["end_turn", "cancelled", "error", "max_tokens", "max_turn_requests", "refusal", "unknown"]);
99
61
  export type StopReason = z.infer<typeof stopReasonSchema>;
100
62
 
101
63
  export const sessionConfigOptionSchema = z.object({
102
64
  /** Agent-defined id; "model" and "mode" are the common ones. */
103
65
  id: z.string(),
104
66
  name: z.string(),
105
- category: z.enum(["model", "mode", "effort", "other"]).default("other"),
67
+ description: z.string().optional(),
68
+ type: z.enum(["select", "boolean"]).optional(),
69
+ category: z.enum(["model", "model_config", "mode", "effort", "other"]).default("other"),
106
70
  current: z.string(),
107
- values: z.array(z.object({ value: z.string(), name: z.string(), description: z.string().optional() })),
71
+ values: z.array(z.object({ value: z.string(), name: z.string(), description: z.string().optional(), group: z.string().optional() })),
108
72
  });
109
73
  export type SessionConfigOption = z.infer<typeof sessionConfigOptionSchema>;
110
74
 
111
75
  export const sessionUpdateSchema = z.discriminatedUnion("sessionUpdate", [
76
+ z.object({
77
+ sessionUpdate: z.literal("ls_message"),
78
+ messageId: z.string(), role: z.enum(["user", "agent", "thought", "session"]),
79
+ parentToolCallId: z.string().optional(),
80
+ content: z.array(contentBlockSchema).optional(),
81
+ append: z.boolean().optional(),
82
+ senderSessionId: z.string().optional(), recipientSessionId: z.string().optional(),
83
+ }),
112
84
  z.object({
113
85
  sessionUpdate: z.literal("user_message_chunk"),
114
86
  messageId: z.string().optional(),
@@ -132,9 +104,11 @@ export const sessionUpdateSchema = z.discriminatedUnion("sessionUpdate", [
132
104
  /** Set when a sub-agent made this call: the sub-agent's own (spawn) tool call. */
133
105
  parentToolCallId: z.string().optional(),
134
106
  title: z.string(),
107
+ name: z.string().optional(),
135
108
  kind: toolKindSchema,
136
109
  status: toolCallStatusSchema,
137
110
  rawInput: z.unknown().optional(),
111
+ rawOutput: z.unknown().optional(),
138
112
  content: z.array(toolCallContentSchema).optional(),
139
113
  locations: z.array(toolCallLocationSchema).optional(),
140
114
  detail: toolDetailSchema.optional(),
@@ -145,16 +119,28 @@ export const sessionUpdateSchema = z.discriminatedUnion("sessionUpdate", [
145
119
  parentToolCallId: z.string().optional(),
146
120
  status: toolCallStatusSchema.optional(),
147
121
  title: z.string().optional(),
122
+ name: z.string().optional(),
123
+ kind: toolKindSchema.optional(),
124
+ rawInput: z.unknown().optional(),
125
+ locations: z.array(toolCallLocationSchema).optional(),
148
126
  detail: toolDetailSchema.optional(),
149
127
  /** Replaces the tool call's content when present. */
150
128
  content: z.array(toolCallContentSchema).optional(),
151
129
  /** Streamed output appended to the tool call's running output. */
152
130
  appendOutput: z.string().optional(),
131
+ replaceOutput: z.string().optional(),
132
+ /** ACP v2 null/empty content clears every previous diff and attachment. */
133
+ replaceContent: z.boolean().optional(),
153
134
  rawOutput: z.unknown().optional(),
154
135
  }),
155
136
  z.object({
156
137
  sessionUpdate: z.literal("plan"),
157
138
  entries: z.array(planEntrySchema),
139
+ planId: z.string().optional(),
140
+ title: z.string().optional(),
141
+ markdown: z.string().nullable().optional(),
142
+ path: z.string().nullable().optional(),
143
+ removed: z.boolean().optional(),
158
144
  }),
159
145
  z.object({
160
146
  sessionUpdate: z.literal("ls_goal"),
@@ -172,13 +158,16 @@ export const sessionUpdateSchema = z.discriminatedUnion("sessionUpdate", [
172
158
  }),
173
159
  z.object({
174
160
  sessionUpdate: z.literal("session_info_update"),
175
- title: z.string().optional(),
161
+ title: z.string().nullable().optional(),
162
+ updatedAt: z.string().nullable().optional(),
176
163
  model: z.string().optional(),
177
164
  }),
178
165
  z.object({
179
166
  sessionUpdate: z.literal("usage_update"),
180
167
  usedTokens: z.number().optional(),
181
168
  contextWindow: z.number().optional(),
169
+ cost: z.object({ amount: z.number(), currency: z.string() }).nullable().optional(),
170
+ tokens: z.object({ totalTokens: z.number(), inputTokens: z.number(), outputTokens: z.number(), thoughtTokens: z.number().nullish(), cachedReadTokens: z.number().nullish(), cachedWriteTokens: z.number().nullish() }).optional(),
182
171
  }),
183
172
  // ── LinkShell extensions ──
184
173
  z.object({
@@ -219,9 +208,13 @@ export const sessionUpdateSchema = z.discriminatedUnion("sessionUpdate", [
219
208
  z.object({
220
209
  sessionUpdate: z.literal("ls_permission"),
221
210
  requestId: z.string(),
211
+ childSessionId: z.string().optional(),
222
212
  toolCallId: z.string().optional(),
223
213
  title: z.string(),
224
214
  detail: z.string().optional(),
215
+ tool: z.object({ title: z.string().optional(), kind: toolKindSchema.optional(), rawInput: z.unknown().optional(), content: z.array(toolCallContentSchema).optional(), locations: z.array(toolCallLocationSchema).optional() }).optional(),
216
+ /** URL interactions stay out of form answers and are opened only after consent. */
217
+ url: z.object({ url: z.string(), elicitationId: z.string() }).optional(),
225
218
  options: z.array(permissionOptionSchema).min(1),
226
219
  /**
227
220
  * The agent is asking the user something: answer with `sessions.answer`.
@@ -245,6 +238,7 @@ export const sessionUpdateSchema = z.discriminatedUnion("sessionUpdate", [
245
238
  z.object({
246
239
  sessionUpdate: z.literal("ls_status"),
247
240
  state: sessionStateSchema,
241
+ turnActive: z.boolean().optional(),
248
242
  }),
249
243
  /** A background task as it is now (the whole record each time: the latest for its id holds). */
250
244
  z.object({
@@ -261,6 +255,10 @@ export const sessionUpdateSchema = z.discriminatedUnion("sessionUpdate", [
261
255
  export type SessionUpdate = z.infer<typeof sessionUpdateSchema>;
262
256
  export type SessionUpdateKind = SessionUpdate["sessionUpdate"];
263
257
 
258
+ /** Live ACP notices are not session history and never change execution state. */
259
+ export const sessionNoticeSchema = z.object({ severity: z.string(), title: z.string(), description: z.string().optional() });
260
+ export type SessionNotice = z.infer<typeof sessionNoticeSchema>;
261
+
264
262
  /** One entry in a session's append-only event log. */
265
263
  export const sessionEventSchema = z.object({
266
264
  sessionId: z.string(),