@hosty-sdk/app 0.38.0 → 0.39.0

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.
@@ -0,0 +1,73 @@
1
+ /** Local-to-Core identities. Never infer an app, conversation, native session or run from another ID. */
2
+ export type ProviderRef = {
3
+ appId: string;
4
+ installationId: string;
5
+ key: string;
6
+ };
7
+ export type ConversationRef = {
8
+ provider: ProviderRef;
9
+ id: string;
10
+ };
11
+ export type NativeSessionRef = {
12
+ provider: ProviderRef;
13
+ id: string;
14
+ };
15
+ export type RunRef = {
16
+ provider: ProviderRef;
17
+ id: string;
18
+ };
19
+ /** Decimal strings avoid integer truncation across language boundaries. */
20
+ export type Revision = string;
21
+ export type AgentSession = {
22
+ ref: NativeSessionRef;
23
+ revision: Revision;
24
+ activeRuns: RunRef[];
25
+ capabilities: string[];
26
+ conversation?: ConversationRef | null;
27
+ };
28
+ export type AgentRun = {
29
+ ref: RunRef;
30
+ revision: Revision;
31
+ state: "queued" | "running" | "waiting_for_input" | "succeeded" | "failed" | "cancelled" | "unknown";
32
+ observedAt: string;
33
+ freshness: "current" | "last_known" | "unavailable";
34
+ stopConfirmed: boolean;
35
+ nativeSession?: NativeSessionRef | null;
36
+ conversation?: ConversationRef | null;
37
+ };
38
+ export type AgentSessionPage = {
39
+ sessions: AgentSession[];
40
+ nextCursor: string | null;
41
+ availability: "available" | "partial" | "unavailable";
42
+ observedAt: string;
43
+ };
44
+ export type AgentSessionQuery = {
45
+ provider: ProviderRef;
46
+ conversation?: ConversationRef;
47
+ cursor?: string;
48
+ limit?: number;
49
+ };
50
+ export type RunCancel = {
51
+ run: RunRef;
52
+ requestId: string;
53
+ expectedRevision: Revision;
54
+ };
55
+ export type RunCancelReceipt = {
56
+ requestId: string;
57
+ state: "accepted" | "completed";
58
+ run: AgentRun;
59
+ };
60
+ export type AgentRunNotification = {
61
+ run: AgentRun;
62
+ cursor: string;
63
+ rescanRequired: boolean;
64
+ };
65
+ export type AgentRunSubscription = {
66
+ handle: string;
67
+ expiresAt: string;
68
+ initial: AgentRunNotification;
69
+ };
70
+ export type AgentRunSubscriptionCreate = {
71
+ run: RunRef;
72
+ cursor?: string;
73
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,354 @@
1
+ import type { ConversationRef, NativeSessionRef, ProviderRef, Revision, RunRef } from "./agent-sessions.js";
2
+ export type { ConversationRef, NativeSessionRef, ProviderRef, Revision, RunRef } from "./agent-sessions.js";
3
+ export type EntryRef = {
4
+ conversation: ConversationRef;
5
+ id: string;
6
+ };
7
+ export type HistoryCoverage = {
8
+ state: "complete" | "partial";
9
+ reasons: string[];
10
+ };
11
+ export type Conversation = {
12
+ ref: ConversationRef;
13
+ revision: Revision;
14
+ title: string | null;
15
+ ownerUserId: string;
16
+ createdAt: string;
17
+ updatedAt: string;
18
+ nativeSessions?: NativeSessionRef[];
19
+ capabilities: string[];
20
+ };
21
+ export type HistoryPart = {
22
+ type: "text";
23
+ text: string;
24
+ format: "plain" | "markdown";
25
+ } | {
26
+ type: "attachment";
27
+ attachmentId: string;
28
+ revision: Revision;
29
+ mediaType: string;
30
+ name: string;
31
+ sizeBytes?: number;
32
+ } | {
33
+ type: "resource";
34
+ resourceKind: string;
35
+ owner: string;
36
+ id: string;
37
+ revision?: Revision;
38
+ label?: string;
39
+ };
40
+ export type Disclosure = "complete" | "redacted" | "truncated";
41
+ export type HistoryData = {
42
+ kind: "message";
43
+ role: "user" | "assistant" | "system";
44
+ parts: HistoryPart[];
45
+ state: "streaming" | "complete" | "interrupted";
46
+ } | {
47
+ kind: "tool_call";
48
+ callId: string;
49
+ toolName: string;
50
+ input: unknown;
51
+ disclosure: Disclosure;
52
+ } | {
53
+ kind: "tool_result";
54
+ callId: string;
55
+ parts: HistoryPart[];
56
+ outcome: "completed" | "failed" | "cancelled" | "unknown";
57
+ durationMs?: number;
58
+ disclosure: Disclosure;
59
+ } | {
60
+ kind: "run_state";
61
+ state: string;
62
+ stopConfirmed: boolean;
63
+ } | {
64
+ kind: "usage";
65
+ scope: "turn" | "run";
66
+ source: string;
67
+ inputTokens?: number;
68
+ outputTokens?: number;
69
+ cachedInputTokens?: number;
70
+ estimated: boolean;
71
+ cost?: {
72
+ amount: string;
73
+ currency: string;
74
+ };
75
+ } | {
76
+ kind: "extension";
77
+ name: string;
78
+ version: number;
79
+ payload: unknown;
80
+ fallbackText?: string;
81
+ disclosure: Disclosure;
82
+ };
83
+ export type HistoryKind = HistoryData["kind"];
84
+ export type HistoryEntry = {
85
+ ref: EntryRef;
86
+ revision: Revision;
87
+ sequence: Revision;
88
+ createdAt: string;
89
+ updatedAt: string;
90
+ actor: {
91
+ kind: "user" | "agent" | "system" | "tool";
92
+ id?: string;
93
+ displayName?: string;
94
+ };
95
+ run?: RunRef;
96
+ parentEntryId?: string;
97
+ data: HistoryData;
98
+ };
99
+ export type HistoryExtension = {
100
+ name: string;
101
+ version: number;
102
+ schema: Record<string, unknown>;
103
+ };
104
+ export type HistoryCapabilities = {
105
+ version: 1;
106
+ entryKinds: HistoryKind[];
107
+ extensions: HistoryExtension[];
108
+ maxPageSize: number;
109
+ snapshotLifetimeSeconds: number;
110
+ changeRetentionSeconds: number;
111
+ };
112
+ export type ConversationQuery = {
113
+ providers: ProviderRef[];
114
+ title?: string;
115
+ cursor?: string;
116
+ limit?: number;
117
+ };
118
+ export type SourceConversationQuery = {
119
+ provider: ProviderRef;
120
+ title?: string;
121
+ cursor?: string;
122
+ limit?: number;
123
+ };
124
+ export type ConversationPage = {
125
+ conversations: Conversation[];
126
+ nextCursor: string | null;
127
+ coverage: HistoryCoverage;
128
+ providers: HistoryProviderCoverage[];
129
+ };
130
+ export type SourceConversationPage = {
131
+ conversations: Conversation[];
132
+ nextCursor: string | null;
133
+ snapshotId: string;
134
+ highWater: Revision;
135
+ coverage: HistoryCoverage;
136
+ };
137
+ export type HistoryQuery = {
138
+ conversation: ConversationRef;
139
+ kinds?: HistoryKind[];
140
+ cursor?: string;
141
+ limit?: number;
142
+ };
143
+ export type HistoryPage = {
144
+ entries: HistoryEntry[];
145
+ nextCursor: string | null;
146
+ snapshotId: string;
147
+ highWater: Revision;
148
+ coverage: HistoryCoverage;
149
+ };
150
+ export type HistoryEntryGet = {
151
+ entry: EntryRef;
152
+ expectedRevision?: Revision;
153
+ };
154
+ export type HistorySearch = {
155
+ providers?: ProviderRef[];
156
+ q: string;
157
+ kinds?: HistoryKind[];
158
+ conversations?: ConversationRef[];
159
+ cursor?: string;
160
+ limit?: number;
161
+ };
162
+ export type HistorySearchHit = {
163
+ entry: EntryRef;
164
+ revision: Revision;
165
+ conversationTitle: string | null;
166
+ excerpt: string;
167
+ updatedAt: string;
168
+ observedAt: string;
169
+ };
170
+ export type HistoryProviderCoverage = {
171
+ provider: ProviderRef;
172
+ state: "complete" | "partial" | "unavailable" | "unsupported";
173
+ error?: HistoryError;
174
+ };
175
+ export type HistorySearchPage = {
176
+ hits: HistorySearchHit[];
177
+ nextCursor: string | null;
178
+ coverage: HistoryCoverage;
179
+ providers: HistoryProviderCoverage[];
180
+ };
181
+ export type HistorySelection = {
182
+ entryIds?: string[];
183
+ includeFutureEntries?: true;
184
+ };
185
+ export type HistoryShareCreate = {
186
+ ref: ConversationRef;
187
+ requestId: string;
188
+ expectedRevision: Revision;
189
+ selection: HistorySelection;
190
+ recipientUserIds: string[];
191
+ includeAttachments: boolean;
192
+ extensions?: string[];
193
+ label?: string;
194
+ expiresAt?: string;
195
+ };
196
+ export type HistoryShare = {
197
+ id: string;
198
+ ref: ConversationRef;
199
+ revision: Revision;
200
+ ownerUserId: string;
201
+ recipientUserIds: string[];
202
+ selection: HistorySelection;
203
+ includeAttachments: boolean;
204
+ extensions: string[];
205
+ label: string | null;
206
+ expiresAt: string | null;
207
+ state: "active" | "revoked";
208
+ };
209
+ export type HistoryShareRevoke = {
210
+ ref: ConversationRef;
211
+ grantId: string;
212
+ requestId: string;
213
+ expectedRevision: Revision;
214
+ };
215
+ export type HistorySharePage = {
216
+ shares: HistoryShare[];
217
+ conversationRevision: Revision;
218
+ };
219
+ export type HistoryShareReceipt = {
220
+ requestId: string;
221
+ grant: HistoryShare;
222
+ conversationRevision: Revision;
223
+ };
224
+ export type HistoryAttachmentResolve = {
225
+ entry: EntryRef;
226
+ attachmentId: string;
227
+ revision: Revision;
228
+ };
229
+ export type HistoryAttachment = {
230
+ attachmentId: string;
231
+ revision: Revision;
232
+ name: string;
233
+ mediaType: string;
234
+ sizeBytes: number;
235
+ handle: string;
236
+ expiresAt: string;
237
+ };
238
+ export type HistoryExportCorpus = {
239
+ mode: "all-owned";
240
+ includeFutureConversations: true;
241
+ providers: ProviderRef[];
242
+ } | {
243
+ mode: "conversations";
244
+ conversations: ConversationRef[];
245
+ };
246
+ export type HistoryExportConsumer = {
247
+ kind: "self";
248
+ } | {
249
+ kind: "app";
250
+ appId: string;
251
+ installationId: string;
252
+ };
253
+ export type HistoryExportCreate = {
254
+ requestId: string;
255
+ consumer: HistoryExportConsumer;
256
+ corpus: HistoryExportCorpus;
257
+ purpose: string;
258
+ expiresAt?: string;
259
+ };
260
+ export type HistoryExportGrant = {
261
+ id: string;
262
+ revision: Revision;
263
+ ownerUserId: string;
264
+ consumer: HistoryExportConsumer;
265
+ principalId: string;
266
+ corpus: HistoryExportCorpus;
267
+ purpose: string;
268
+ expiresAt: string | null;
269
+ state: "proposed" | "active";
270
+ approvalUrl?: string | null;
271
+ lastAppliedCursor?: string | null;
272
+ } | {
273
+ id: string;
274
+ revision: Revision;
275
+ state: "purge_required" | "purged";
276
+ ownerUserId?: string | null;
277
+ consumer?: HistoryExportConsumer | null;
278
+ principalId?: string | null;
279
+ corpus?: HistoryExportCorpus | null;
280
+ purpose?: string | null;
281
+ expiresAt?: string | null;
282
+ approvalUrl?: null;
283
+ lastAppliedCursor?: string | null;
284
+ };
285
+ export type HistoryExportQuery = {
286
+ exportGrantId: string;
287
+ provider: ProviderRef;
288
+ cursor?: string;
289
+ limit?: number;
290
+ };
291
+ export type HistoryExportSnapshot = {
292
+ entries: HistoryEntry[];
293
+ nextCursor: string | null;
294
+ snapshotId: string;
295
+ highWater: Revision;
296
+ changeCursor: string;
297
+ coverage: HistoryCoverage;
298
+ };
299
+ export type HistoryChange = {
300
+ id: string;
301
+ sequence: Revision;
302
+ type: "upsert";
303
+ entry: HistoryEntry;
304
+ } | {
305
+ id: string;
306
+ sequence: Revision;
307
+ type: "delete";
308
+ ref: EntryRef;
309
+ revision: Revision;
310
+ } | {
311
+ id: string;
312
+ sequence: Revision;
313
+ type: "access_reset";
314
+ reason: string;
315
+ };
316
+ export type HistoryChangePage = {
317
+ changes: HistoryChange[];
318
+ nextCursor: string;
319
+ highWater: Revision;
320
+ coverage: HistoryCoverage;
321
+ };
322
+ export type HistoryExportAcknowledge = {
323
+ exportGrantId: string;
324
+ requestId: string;
325
+ expectedRevision: Revision;
326
+ lastAppliedCursor?: string;
327
+ purgeComplete?: boolean;
328
+ };
329
+ export type HistoryError = {
330
+ code: string;
331
+ message: string;
332
+ retryable: boolean;
333
+ operationRef?: string;
334
+ };
335
+ export type HistoryNotification = {
336
+ conversation: ConversationRef;
337
+ revision: Revision;
338
+ cursor: string;
339
+ changes: Array<{
340
+ type: "upsert" | "delete";
341
+ entryId: string;
342
+ revision: Revision;
343
+ }>;
344
+ rescanRequired: boolean;
345
+ };
346
+ export type HistorySubscription = {
347
+ handle: string;
348
+ expiresAt: string;
349
+ initial: HistoryNotification;
350
+ };
351
+ export type HistorySubscriptionCreate = {
352
+ conversation: ConversationRef;
353
+ cursor?: string;
354
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,5 +1,6 @@
1
+ import type { HistoryExportGrant, HistoryExportAcknowledge, HistoryExportQuery, HistoryExportSnapshot, HistoryChangePage } from "./history.js";
1
2
  import { AssistantClient } from "@hosty-sdk/app/assistant";
2
- import { type AppPermissionState, type ProviderDescriptor, type ProviderInvocation, type ProviderKind, type SpeechCapabilities, type SpeechResult, type TranslationRequest, type TranslationResult, type TranslationCapabilities } from "@hosty-sdk/app/providers";
3
+ import { type AppPermissionState, type ProviderDescriptor, type ProviderInvocation, type ProviderKind, type MediatedProviderInvocation, type MediatedProviderRequest, type SpeechCapabilities, type SpeechResult, type TranslationRequest, type TranslationResult, type TranslationCapabilities } from "@hosty-sdk/app/providers";
3
4
  export type ProviderServerOptions = {
4
5
  appId?: string;
5
6
  coreOrigin?: string;
@@ -15,6 +16,19 @@ export declare class ProviderClient {
15
16
  private readonly container;
16
17
  constructor(options?: ProviderServerOptions);
17
18
  private coreRequest;
19
+ /** Recover only an already-authorized immutable task attempt; service identity alone grants no user authority. */
20
+ taskDispatch<T>(input: import("./providers.js").TaskDispatchRequest, signal?: AbortSignal): Promise<T>;
21
+ /** No general user/source credential is minted; the original attempt and grants remain authoritative. */
22
+ taskWorkspace<T>(input: import("./providers.js").TaskWorkspaceRequest, signal?: AbortSignal): Promise<T>;
23
+ taskDispatchAuthority(dispatch: import("./providers.js").TaskDispatchRef, signal?: AbortSignal): Promise<{
24
+ dispatch: import("./providers.js").TaskDispatchRef;
25
+ scope: import("./providers.js").TaskDispatchScope;
26
+ }>;
27
+ /** The service identity accesses only export grants explicitly approved for this installation. */
28
+ historyExportGet(exportGrantId: string, signal?: AbortSignal): Promise<HistoryExportGrant>;
29
+ historyExportAcknowledge(input: HistoryExportAcknowledge, signal?: AbortSignal): Promise<HistoryExportGrant>;
30
+ historyExportSnapshot(input: HistoryExportQuery, signal?: AbortSignal): Promise<HistoryExportSnapshot>;
31
+ historyExportChanges(input: HistoryExportQuery, signal?: AbortSignal): Promise<HistoryChangePage>;
18
32
  permissions(signal?: AbortSignal): Promise<AppPermissionState>;
19
33
  list(kind: ProviderKind, signal?: AbortSignal): Promise<ProviderDescriptor[]>;
20
34
  private connect;
@@ -32,6 +46,8 @@ export declare class ProviderClient {
32
46
  }, userToken: () => Promise<string>): Promise<AssistantClient>;
33
47
  /** Bounded task protocol transport. The selected installation is checked on every operation. */
34
48
  taskRequest<T>(provider: import("./tasks.js").TaskProviderRef, kind: "tasks" | "task-executor", route: string, method: string, input?: unknown, userToken?: () => Promise<string>, signal?: AbortSignal): Promise<T>;
49
+ /** Validate an operation-bound Core credential against this exact request. Source ACL checks remain mandatory. */
50
+ validateMediated(token: string, kind: ProviderKind, request: MediatedProviderRequest, key?: string, signal?: AbortSignal): Promise<MediatedProviderInvocation>;
35
51
  /** Provider-side validation checks live grants on every request; never cache this result. */
36
52
  validate(token: string, kind: ProviderKind, key?: string, signal?: AbortSignal): Promise<ProviderInvocation>;
37
53
  }
@@ -1,3 +1,4 @@
1
+ import { createHash } from "node:crypto";
1
2
  import { AssistantClient } from "@hosty-sdk/app/assistant";
2
3
  import { ProviderError } from "@hosty-sdk/app/providers";
3
4
  /** Server-only provider client. Its app service token must never be sent to a browser or provider. */
@@ -23,6 +24,22 @@ export class ProviderClient {
23
24
  });
24
25
  return read(response);
25
26
  }
27
+ /** Recover only an already-authorized immutable task attempt; service identity alone grants no user authority. */
28
+ taskDispatch(input, signal) {
29
+ return this.coreRequest("/task-dispatch", input, signal);
30
+ }
31
+ /** No general user/source credential is minted; the original attempt and grants remain authoritative. */
32
+ taskWorkspace(input, signal) {
33
+ return this.coreRequest("/task-workspace", input, signal);
34
+ }
35
+ taskDispatchAuthority(dispatch, signal) {
36
+ return this.coreRequest("/task-dispatch-authority", { dispatch }, signal);
37
+ }
38
+ /** The service identity accesses only export grants explicitly approved for this installation. */
39
+ historyExportGet(exportGrantId, signal) { return this.coreRequest("/history-exports/get", { exportGrantId }, signal); }
40
+ historyExportAcknowledge(input, signal) { return this.coreRequest("/history-exports/acknowledge", input, signal); }
41
+ historyExportSnapshot(input, signal) { return this.coreRequest("/history-exports/snapshot", input, signal); }
42
+ historyExportChanges(input, signal) { return this.coreRequest("/history-exports/changes", input, signal); }
26
43
  permissions(signal) { return this.coreRequest("/permissions", undefined, signal); }
27
44
  async list(kind, signal) {
28
45
  return (await this.coreRequest(`/providers/${kind}`, undefined, signal)).providers;
@@ -92,6 +109,20 @@ export class ProviderClient {
92
109
  headers: { authorization: `Bearer ${binding.token}`, "content-type": "application/json" },
93
110
  body: input === undefined ? undefined : JSON.stringify(input) }));
94
111
  }
112
+ /** Validate an operation-bound Core credential against this exact request. Source ACL checks remain mandatory. */
113
+ async validateMediated(token, kind, request, key = "default", signal) {
114
+ if (!token.startsWith("hosty_provider.2.") || !request.path.startsWith("/") || request.path.startsWith("//")
115
+ || !["GET", "POST", "PATCH", "PUT", "DELETE"].includes(request.method) || Buffer.byteLength(request.body) > 1024 * 1024)
116
+ throw new ProviderError("token_invalid", "A bounded, exact Core-mediated provider request is required.", 401);
117
+ const invocation = await this.coreRequest("/provider/introspect-v2", {
118
+ token, kind, key, operation: request.operation, method: request.method, path: request.path,
119
+ bodyHash: createHash("sha256").update(request.body).digest("hex"),
120
+ }, signal);
121
+ if (invocation.version !== 2 || invocation.kind !== kind || invocation.key !== key || invocation.operation !== request.operation
122
+ || !invocation.userId || !invocation.principalId || !Array.isArray(invocation.resourceIds))
123
+ throw new ProviderError("token_invalid", "Core returned an invalid mediated invocation.", 401);
124
+ return invocation;
125
+ }
95
126
  /** Provider-side validation checks live grants on every request; never cache this result. */
96
127
  validate(token, kind, key = "default", signal) {
97
128
  return this.coreRequest("/provider/introspect", { token, kind, key }, signal);
@@ -99,8 +130,9 @@ export class ProviderClient {
99
130
  }
100
131
  async function read(response) {
101
132
  const body = await response.json().catch(() => null);
133
+ const error = body?.error ?? body;
102
134
  if (!response.ok)
103
- throw new ProviderError(body?.code ?? "provider_failed", body?.message ?? `Provider request failed (${response.status}).`, response.status);
135
+ throw new ProviderError(error?.code ?? "provider_failed", error?.message ?? `Provider request failed (${response.status}).`, response.status);
104
136
  if (body === null)
105
137
  throw new ProviderError("provider_response_invalid", "Provider returned an invalid response.", 502);
106
138
  return body;
@@ -1,5 +1,5 @@
1
1
  /** Provider categories supported by Core. Task execution does not expose model/profile configuration. */
2
- export type ProviderKind = "speech-to-text" | "assistant" | "translation" | "tasks" | "task-executor";
2
+ export type ProviderKind = "speech-to-text" | "assistant" | "translation" | "tasks" | "task-executor" | "conversation-history" | "agent-sessions";
3
3
  export type ProviderDescriptor = {
4
4
  appId: string;
5
5
  displayName: string;
@@ -36,6 +36,39 @@ export type ProviderInvocation = {
36
36
  kind: ProviderKind;
37
37
  key: string;
38
38
  };
39
+ /** Core-mediated v2 invocations carry the original principal; direct clients have no app identity. */
40
+ export type MediatedProviderInvocation = {
41
+ version: 2;
42
+ callerAppId: string | null;
43
+ callerInstallation: string | null;
44
+ userId: string;
45
+ hostRole: string;
46
+ principalId: string;
47
+ kind: ProviderKind;
48
+ key: string;
49
+ operation: string;
50
+ resourceIds: string[];
51
+ taskDispatch?: TaskDispatchRef | null;
52
+ taskDelegation?: {
53
+ dispatch: TaskDispatchRef;
54
+ taskRef: import("./tasks.js").TaskRef;
55
+ executionId: string | null;
56
+ } | null;
57
+ export?: {
58
+ grantId: string;
59
+ revision: string;
60
+ ownerUserId: string;
61
+ provider: import("./agent-sessions.js").ProviderRef;
62
+ conversationIds: string[] | null;
63
+ } | null;
64
+ };
65
+ /** The provider computes these values from the actual incoming request, never from unverified claims. */
66
+ export type MediatedProviderRequest = {
67
+ operation: string;
68
+ method: string;
69
+ path: string;
70
+ body: Uint8Array | string;
71
+ };
39
72
  export type SpeechResult = {
40
73
  text: string;
41
74
  language?: string | null;
@@ -77,3 +110,45 @@ export declare class ProviderError extends Error {
77
110
  readonly status: number;
78
111
  constructor(code: string, message: string, status: number);
79
112
  }
113
+ /** Non-secret receipt reference. Only its reviewed source and executor installations can use it. */
114
+ export type TaskDispatchRef = {
115
+ userId: string;
116
+ principalId: string;
117
+ requestId: string;
118
+ };
119
+ export type TaskDispatchScope = {
120
+ taskRef: import("./tasks.js").TaskRef;
121
+ executor: import("./tasks.js").TaskProviderRef;
122
+ inputRevision: number;
123
+ inputHash: string;
124
+ optionId: string | null;
125
+ executionId: string | null;
126
+ workspaceId?: string | null;
127
+ };
128
+ export type TaskDispatchRequest = {
129
+ dispatch: TaskDispatchRef;
130
+ executor: import("./tasks.js").TaskProviderRef;
131
+ operation: "options" | "get" | "accept" | "cancel";
132
+ executionId?: string;
133
+ input?: import("./tasks.js").TaskExecutionInput;
134
+ requestId?: string;
135
+ };
136
+ /** Executor-only access to the workspace already selected by an immutable task attempt. */
137
+ export type TaskWorkspaceRequest = {
138
+ dispatch: TaskDispatchRef;
139
+ executionId: string;
140
+ sessionId: string;
141
+ leaseId: string;
142
+ kind: "observe" | "attach" | "lease" | "activity";
143
+ requestId?: string;
144
+ expectedRevision?: number;
145
+ title?: string;
146
+ navigationPath?: string;
147
+ activity?: {
148
+ status: string;
149
+ leaseId: string;
150
+ stopped?: boolean;
151
+ title?: string;
152
+ sequence?: number;
153
+ };
154
+ };
@@ -31,3 +31,14 @@ export declare class TaskExecutorClient {
31
31
  get(executionId: string, signal?: AbortSignal): Promise<TaskExecutionReceipt>;
32
32
  cancel(executionId: string, requestId: string, signal?: AbortSignal): Promise<TaskExecutionReceipt>;
33
33
  }
34
+ /** Core-mediated child calls retain the original caller and the exact task-provider attribution. */
35
+ export declare class MediatedTaskExecutorClient {
36
+ private readonly providers;
37
+ private readonly executor;
38
+ private readonly dispatch;
39
+ constructor(providers: ProviderClient, executor: TaskProviderRef, dispatch: import("./providers.js").TaskDispatchRef);
40
+ options(signal?: AbortSignal): Promise<TaskExecutorOptions>;
41
+ get(executionId: string, signal?: AbortSignal): Promise<TaskExecutionReceipt>;
42
+ accept(executionId: string, input: TaskExecutionInput, signal?: AbortSignal): Promise<TaskExecutionReceipt>;
43
+ cancel(executionId: string, requestId: string, signal?: AbortSignal): Promise<TaskExecutionReceipt>;
44
+ }
@@ -55,3 +55,18 @@ export class TaskExecutorClient {
55
55
  return this.call(`/executions/${encodeURIComponent(executionId)}/cancel`, "POST", { requestId }, signal);
56
56
  }
57
57
  }
58
+ /** Core-mediated child calls retain the original caller and the exact task-provider attribution. */
59
+ export class MediatedTaskExecutorClient {
60
+ providers;
61
+ executor;
62
+ dispatch;
63
+ constructor(providers, executor, dispatch) {
64
+ this.providers = providers;
65
+ this.executor = executor;
66
+ this.dispatch = dispatch;
67
+ }
68
+ options(signal) { return this.providers.taskDispatch({ dispatch: this.dispatch, executor: this.executor, operation: "options" }, signal); }
69
+ get(executionId, signal) { return this.providers.taskDispatch({ dispatch: this.dispatch, executor: this.executor, operation: "get", executionId }, signal); }
70
+ accept(executionId, input, signal) { return this.providers.taskDispatch({ dispatch: this.dispatch, executor: this.executor, operation: "accept", executionId, input }, signal); }
71
+ cancel(executionId, requestId, signal) { return this.providers.taskDispatch({ dispatch: this.dispatch, executor: this.executor, operation: "cancel", executionId, requestId }, signal); }
72
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hosty-sdk/app",
3
- "version": "0.38.0",
3
+ "version": "0.39.0",
4
4
  "description": "Hosty app auth: session state machine, recovery bridge, Core revalidation, and the embedder responder.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "type": "module",
@@ -148,6 +148,14 @@
148
148
  "./feedback/server": {
149
149
  "types": "./dist/feedback-server.d.ts",
150
150
  "default": "./dist/feedback-server.js"
151
+ },
152
+ "./agent-sessions": {
153
+ "types": "./dist/agent-sessions.d.ts",
154
+ "default": "./dist/agent-sessions.js"
155
+ },
156
+ "./history": {
157
+ "types": "./dist/history.d.ts",
158
+ "default": "./dist/history.js"
151
159
  }
152
160
  },
153
161
  "scripts": {