@sentry/junior 0.71.3 → 0.72.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.
- package/bin/junior.mjs +10 -0
- package/dist/api-reference.d.ts +2 -0
- package/dist/app.d.ts +5 -5
- package/dist/app.js +1039 -1971
- package/dist/chat/agent-dispatch/heartbeat.d.ts +0 -6
- package/dist/chat/mcp/errors.d.ts +3 -0
- package/dist/chat/mcp/tool-manager.d.ts +5 -1
- package/dist/chat/plugins/agent-hooks.d.ts +3 -2
- package/dist/chat/requester.d.ts +60 -0
- package/dist/chat/respond.d.ts +2 -6
- package/dist/chat/runtime/agent-continue-runner.d.ts +25 -0
- package/dist/chat/runtime/reply-executor.d.ts +4 -4
- package/dist/chat/runtime/turn.d.ts +2 -2
- package/dist/chat/services/agent-continue.d.ts +27 -0
- package/dist/chat/services/message-actor-identity.d.ts +12 -4
- package/dist/chat/services/turn-session-record.d.ts +10 -7
- package/dist/chat/slack/user.d.ts +4 -4
- package/dist/chat/state/adapter.d.ts +2 -0
- package/dist/chat/state/conversation-details.d.ts +4 -3
- package/dist/chat/state/session-log.d.ts +43 -0
- package/dist/chat/state/turn-session.d.ts +7 -10
- package/dist/chat/task-execution/slack-work.d.ts +5 -5
- package/dist/chat/task-execution/store.d.ts +83 -48
- package/dist/chat/task-execution/worker.d.ts +3 -3
- package/dist/chat/tools/definition.d.ts +3 -0
- package/dist/chat/tools/execution/tool-error-handler.d.ts +2 -1
- package/dist/chat/tools/types.d.ts +2 -5
- package/dist/{chunk-R62YWUNO.js → chunk-3FYPXHPL.js} +10 -28
- package/dist/chunk-4JXCSGSA.js +212 -0
- package/dist/{chunk-GT67ZWZQ.js → chunk-55XEZFGD.js} +5 -3
- package/dist/{chunk-BBXYXOJW.js → chunk-6GEYPE6T.js} +18 -523
- package/dist/chunk-G3E7SCME.js +28 -0
- package/dist/{chunk-UXG6TU2U.js → chunk-GB3AL54K.js} +8 -93
- package/dist/chunk-HNMUVGSR.js +1119 -0
- package/dist/{chunk-XE2VFQQN.js → chunk-ICKIDP7G.js} +1 -1
- package/dist/chunk-KVZL5NZS.js +519 -0
- package/dist/chunk-PP7AGSBU.js +185 -0
- package/dist/{chunk-B5HKWWQB.js → chunk-VLIO6RQR.js} +8 -6
- package/dist/{chunk-HOGQL2H6.js → chunk-VSNA5KAB.js} +177 -101
- package/dist/{chunk-76YMBKW7.js → chunk-XC33FJZN.js} +4 -12
- package/dist/{chunk-JS4HURDT.js → chunk-ZJQPA67D.js} +25 -25
- package/dist/cli/check.js +10 -8
- package/dist/cli/run.js +9 -1
- package/dist/cli/snapshot-warmup.js +10 -7
- package/dist/cli/upgrade.js +599 -0
- package/dist/nitro.d.ts +1 -1
- package/dist/nitro.js +5 -4
- package/dist/plugins.d.ts +1 -1
- package/dist/reporting/conversations.d.ts +116 -0
- package/dist/reporting.d.ts +24 -129
- package/dist/reporting.js +310 -158
- package/package.json +3 -3
- package/dist/chat/runtime/timeout-resume-runner.d.ts +0 -19
- package/dist/chat/services/requester-identity.d.ts +0 -19
- package/dist/chat/services/timeout-resume.d.ts +0 -23
- package/dist/handlers/turn-resume.d.ts +0 -4
|
@@ -1,59 +1,85 @@
|
|
|
1
1
|
import type { StateAdapter } from "chat";
|
|
2
2
|
import type { Destination } from "@sentry/junior-plugin-api";
|
|
3
|
+
import { type StoredSlackRequester } from "@/chat/requester";
|
|
3
4
|
import type { ConversationWorkQueue } from "./queue";
|
|
5
|
+
export declare const CONVERSATION_BY_ACTIVITY_INDEX_KEY = "junior:conversation:by-activity";
|
|
6
|
+
export declare const CONVERSATION_ACTIVE_INDEX_KEY = "junior:conversation:active";
|
|
4
7
|
export declare const CONVERSATION_WORK_LEASE_TTL_MS = 90000;
|
|
5
8
|
export declare const CONVERSATION_WORK_CHECK_IN_INTERVAL_MS = 15000;
|
|
6
9
|
export declare const CONVERSATION_WORK_STALE_ENQUEUE_MS = 60000;
|
|
7
|
-
export
|
|
8
|
-
export type
|
|
9
|
-
export interface
|
|
10
|
+
export type Source = "api" | "internal" | "plugin" | "scheduler" | "slack";
|
|
11
|
+
export type ExecutionStatus = "awaiting_resume" | "idle" | "pending" | "running";
|
|
12
|
+
export interface AgentInput {
|
|
10
13
|
attachments?: unknown[];
|
|
11
14
|
authorId?: string;
|
|
12
15
|
metadata?: Record<string, unknown>;
|
|
13
16
|
text: string;
|
|
14
17
|
}
|
|
15
|
-
export interface
|
|
18
|
+
export interface InboundMessage {
|
|
16
19
|
conversationId: string;
|
|
17
20
|
createdAtMs: number;
|
|
18
21
|
destination: Destination;
|
|
19
22
|
inboundMessageId: string;
|
|
20
23
|
injectedAtMs?: number;
|
|
21
|
-
input:
|
|
24
|
+
input: AgentInput;
|
|
22
25
|
receivedAtMs: number;
|
|
23
|
-
source:
|
|
26
|
+
source: Source;
|
|
24
27
|
}
|
|
25
|
-
export interface
|
|
28
|
+
export interface Lease {
|
|
29
|
+
acquiredAtMs: number;
|
|
30
|
+
expiresAtMs: number;
|
|
31
|
+
lastCheckInAtMs: number;
|
|
32
|
+
token: string;
|
|
33
|
+
}
|
|
34
|
+
export interface ConversationExecution {
|
|
35
|
+
inboundMessageIds: string[];
|
|
36
|
+
lastCheckpointAtMs?: number;
|
|
37
|
+
lastEnqueuedAtMs?: number;
|
|
38
|
+
lease?: Lease;
|
|
39
|
+
pendingCount: number;
|
|
40
|
+
pendingMessages: InboundMessage[];
|
|
41
|
+
runId?: string;
|
|
42
|
+
status: ExecutionStatus;
|
|
43
|
+
updatedAtMs?: number;
|
|
44
|
+
}
|
|
45
|
+
export interface Conversation {
|
|
46
|
+
channelName?: string;
|
|
47
|
+
conversationId: string;
|
|
48
|
+
createdAtMs: number;
|
|
49
|
+
destination?: Destination;
|
|
50
|
+
execution: ConversationExecution;
|
|
51
|
+
lastActivityAtMs: number;
|
|
52
|
+
requester?: StoredSlackRequester;
|
|
53
|
+
schemaVersion: 1;
|
|
54
|
+
source?: Source;
|
|
55
|
+
title?: string;
|
|
56
|
+
updatedAtMs: number;
|
|
57
|
+
}
|
|
58
|
+
export interface ConversationWorkLease {
|
|
26
59
|
acquiredAtMs: number;
|
|
27
60
|
lastCheckInAtMs: number;
|
|
28
61
|
leaseExpiresAtMs: number;
|
|
29
62
|
leaseToken: string;
|
|
30
63
|
}
|
|
31
|
-
export interface ConversationWorkState {
|
|
32
|
-
consecutiveFailureCount: number;
|
|
33
|
-
conversationId: string;
|
|
34
|
-
destination: Destination;
|
|
64
|
+
export interface ConversationWorkState extends Conversation {
|
|
35
65
|
lastEnqueuedAtMs?: number;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
messages: InboundMessageRecord[];
|
|
66
|
+
lease?: ConversationWorkLease;
|
|
67
|
+
messages: InboundMessage[];
|
|
39
68
|
needsRun: boolean;
|
|
40
|
-
schemaVersion: 1;
|
|
41
|
-
terminallyFailedAtMs?: number;
|
|
42
|
-
updatedAtMs: number;
|
|
43
69
|
}
|
|
44
|
-
export interface
|
|
70
|
+
export interface StartConversationWorkAcquired {
|
|
45
71
|
leaseExpiresAtMs: number;
|
|
46
72
|
leaseToken: string;
|
|
47
73
|
status: "acquired";
|
|
48
74
|
}
|
|
49
|
-
export interface
|
|
75
|
+
export interface StartConversationWorkActive {
|
|
50
76
|
leaseExpiresAtMs: number;
|
|
51
77
|
status: "active";
|
|
52
78
|
}
|
|
53
|
-
export interface
|
|
79
|
+
export interface StartConversationWorkNoWork {
|
|
54
80
|
status: "no_work";
|
|
55
81
|
}
|
|
56
|
-
export type
|
|
82
|
+
export type StartConversationWorkResult = StartConversationWorkAcquired | StartConversationWorkActive | StartConversationWorkNoWork;
|
|
57
83
|
export interface AppendInboundMessageResult {
|
|
58
84
|
status: "appended" | "duplicate";
|
|
59
85
|
}
|
|
@@ -63,24 +89,29 @@ export interface AppendAndEnqueueInboundMessageResult extends AppendInboundMessa
|
|
|
63
89
|
export interface RequestConversationWorkResult {
|
|
64
90
|
status: "created" | "updated";
|
|
65
91
|
}
|
|
66
|
-
/** Return a persisted conversation
|
|
92
|
+
/** Return a persisted conversation record, if one exists. */
|
|
93
|
+
export declare function getConversation(args: {
|
|
94
|
+
conversationId: string;
|
|
95
|
+
state?: StateAdapter;
|
|
96
|
+
}): Promise<Conversation | undefined>;
|
|
97
|
+
/** Return a persisted conversation record, if one exists. */
|
|
67
98
|
export declare function getConversationWorkState(args: {
|
|
68
99
|
conversationId: string;
|
|
69
100
|
state?: StateAdapter;
|
|
70
101
|
}): Promise<ConversationWorkState | undefined>;
|
|
71
102
|
/** Count mailbox messages that have not yet reached the session log. */
|
|
72
|
-
export declare function countPendingConversationMessages(
|
|
103
|
+
export declare function countPendingConversationMessages(conversation: Conversation): number;
|
|
73
104
|
/** Return whether a conversation has pending or resumable execution work. */
|
|
74
|
-
export declare function hasRunnableConversationWork(
|
|
105
|
+
export declare function hasRunnableConversationWork(conversation: Conversation): boolean;
|
|
75
106
|
/** Persist one inbound message idempotently in its conversation mailbox. */
|
|
76
107
|
export declare function appendInboundMessage(args: {
|
|
77
|
-
message:
|
|
108
|
+
message: InboundMessage;
|
|
78
109
|
nowMs?: number;
|
|
79
110
|
state?: StateAdapter;
|
|
80
111
|
}): Promise<AppendInboundMessageResult>;
|
|
81
112
|
/** Persist inbound work and send the queue nudge that wakes a worker. */
|
|
82
113
|
export declare function appendAndEnqueueInboundMessage(args: {
|
|
83
|
-
message:
|
|
114
|
+
message: InboundMessage;
|
|
84
115
|
nowMs?: number;
|
|
85
116
|
queue: ConversationWorkQueue;
|
|
86
117
|
state?: StateAdapter;
|
|
@@ -92,6 +123,18 @@ export declare function requestConversationWork(args: {
|
|
|
92
123
|
nowMs?: number;
|
|
93
124
|
state?: StateAdapter;
|
|
94
125
|
}): Promise<RequestConversationWorkResult>;
|
|
126
|
+
/** Record visible conversation activity without making the conversation runnable. */
|
|
127
|
+
export declare function recordConversationActivity(args: {
|
|
128
|
+
activityAtMs?: number;
|
|
129
|
+
channelName?: string;
|
|
130
|
+
conversationId: string;
|
|
131
|
+
destination?: Destination;
|
|
132
|
+
nowMs?: number;
|
|
133
|
+
requester?: StoredSlackRequester;
|
|
134
|
+
source?: Source;
|
|
135
|
+
state?: StateAdapter;
|
|
136
|
+
title?: string;
|
|
137
|
+
}): Promise<void>;
|
|
95
138
|
/** Record that a wake-up nudge was accepted for the conversation. */
|
|
96
139
|
export declare function markConversationWorkEnqueued(args: {
|
|
97
140
|
conversationId: string;
|
|
@@ -103,7 +146,7 @@ export declare function startConversationWork(args: {
|
|
|
103
146
|
conversationId: string;
|
|
104
147
|
nowMs?: number;
|
|
105
148
|
state?: StateAdapter;
|
|
106
|
-
}): Promise<
|
|
149
|
+
}): Promise<StartConversationWorkResult>;
|
|
107
150
|
/** Extend the durable execution lease when the worker checks in. */
|
|
108
151
|
export declare function checkInConversationWork(args: {
|
|
109
152
|
conversationId: string;
|
|
@@ -114,11 +157,11 @@ export declare function checkInConversationWork(args: {
|
|
|
114
157
|
/** Drain pending mailbox entries after the caller has durably injected them. */
|
|
115
158
|
export declare function drainConversationMailbox(args: {
|
|
116
159
|
conversationId: string;
|
|
117
|
-
inject: (messages:
|
|
160
|
+
inject: (messages: InboundMessage[]) => Promise<void>;
|
|
118
161
|
leaseToken: string;
|
|
119
162
|
nowMs?: number;
|
|
120
163
|
state?: StateAdapter;
|
|
121
|
-
}): Promise<
|
|
164
|
+
}): Promise<InboundMessage[]>;
|
|
122
165
|
/** Mark selected leased mailbox entries after their session-log injection succeeds. */
|
|
123
166
|
export declare function markConversationMessagesInjected(args: {
|
|
124
167
|
conversationId: string;
|
|
@@ -155,27 +198,19 @@ export declare function clearExpiredConversationLease(args: {
|
|
|
155
198
|
nowMs?: number;
|
|
156
199
|
state?: StateAdapter;
|
|
157
200
|
}): Promise<boolean>;
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
consecutiveFailureCount: number;
|
|
161
|
-
releasedLease: boolean;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Increment the durable failure counter after a caught worker error so
|
|
165
|
-
* deterministic poison work cannot churn the queue forever. When the counter
|
|
166
|
-
* crosses {@link CONVERSATION_WORK_MAX_CONSECUTIVE_FAILURES}, the conversation
|
|
167
|
-
* is marked terminally failed: the lease is cleared, pending mailbox messages
|
|
168
|
-
* are dropped, and the conversation drops out of the recovery index so neither
|
|
169
|
-
* the worker nor heartbeat will requeue it again. A later inbound message
|
|
170
|
-
* resets the counter and gives the conversation a fresh attempt.
|
|
171
|
-
*/
|
|
172
|
-
export declare function recordConversationWorkFailure(args: {
|
|
201
|
+
/** Remove one conversation from the active index after it is missing or idle. */
|
|
202
|
+
export declare function removeActiveConversation(args: {
|
|
173
203
|
conversationId: string;
|
|
174
|
-
nowMs?: number;
|
|
175
204
|
state?: StateAdapter;
|
|
176
|
-
}): Promise<
|
|
177
|
-
/** List
|
|
178
|
-
export declare function
|
|
205
|
+
}): Promise<void>;
|
|
206
|
+
/** List active conversation ids by oldest execution update first. */
|
|
207
|
+
export declare function listActiveConversationIds(args?: {
|
|
179
208
|
limit?: number;
|
|
209
|
+
staleBeforeMs?: number;
|
|
180
210
|
state?: StateAdapter;
|
|
181
211
|
}): Promise<string[]>;
|
|
212
|
+
/** List retained conversations by newest visible activity first. */
|
|
213
|
+
export declare function listConversationsByActivity(args?: {
|
|
214
|
+
limit?: number;
|
|
215
|
+
state?: StateAdapter;
|
|
216
|
+
}): Promise<Conversation[]>;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { StateAdapter } from "chat";
|
|
2
2
|
import type { Destination } from "@sentry/junior-plugin-api";
|
|
3
3
|
import { type ConversationQueueMessage, type ConversationWorkQueue } from "./queue";
|
|
4
|
-
import { type
|
|
4
|
+
import { type InboundMessage } from "./store";
|
|
5
5
|
export declare const CONVERSATION_WORK_DEFER_DELAY_MS = 15000;
|
|
6
6
|
export declare const CONVERSATION_WORK_SOFT_YIELD_AFTER_MS = 240000;
|
|
7
7
|
export interface ConversationWorkerContext {
|
|
8
8
|
checkIn(): Promise<boolean>;
|
|
9
9
|
conversationId: string;
|
|
10
10
|
destination: Destination;
|
|
11
|
-
drainMailbox(inject: (messages:
|
|
11
|
+
drainMailbox(inject: (messages: InboundMessage[]) => Promise<void>): Promise<InboundMessage[]>;
|
|
12
12
|
leaseToken: string;
|
|
13
13
|
shouldYield(): boolean;
|
|
14
14
|
}
|
|
@@ -16,7 +16,7 @@ export interface ConversationWorkerResult {
|
|
|
16
16
|
status: "completed" | "lost_lease" | "yielded";
|
|
17
17
|
}
|
|
18
18
|
export interface ConversationWorkProcessResult {
|
|
19
|
-
status: "
|
|
19
|
+
status: "active" | "completed" | "lost_lease" | "no_work" | "pending_requeued" | "yielded";
|
|
20
20
|
}
|
|
21
21
|
export interface ProcessConversationWorkOptions {
|
|
22
22
|
checkInIntervalMs?: number;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
|
|
2
2
|
import type { Static, TSchema } from "@sinclair/typebox";
|
|
3
3
|
import type { ToolExecutionMode } from "@earendil-works/pi-agent-core";
|
|
4
|
+
import type { ConversationPrivacy } from "@/chat/conversation-privacy";
|
|
4
5
|
export interface ToolDefinition<TInputSchema extends TSchema = TSchema> {
|
|
5
6
|
description: string;
|
|
6
7
|
inputSchema: TInputSchema;
|
|
@@ -22,6 +23,8 @@ export interface ToolDefinition<TInputSchema extends TSchema = TSchema> {
|
|
|
22
23
|
execute?: (input: Static<TInputSchema>, options: {
|
|
23
24
|
experimental_context?: unknown;
|
|
24
25
|
signal?: AbortSignal;
|
|
26
|
+
conversationPrivacy?: ConversationPrivacy;
|
|
27
|
+
toolCallId?: string;
|
|
25
28
|
}) => Promise<unknown> | unknown;
|
|
26
29
|
}
|
|
27
30
|
/** Infer execute parameter types from the inputSchema via generic binding. */
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { type LogContext } from "@/chat/logging";
|
|
2
|
+
import type { ConversationPrivacy } from "@/chat/conversation-privacy";
|
|
2
3
|
/** Handle tool execution errors: set span attributes, log, and rethrow. */
|
|
3
|
-
export declare function handleToolExecutionError(error: unknown, toolName: string, toolCallId: string | undefined, shouldTrace: boolean, traceContext: LogContext): never;
|
|
4
|
+
export declare function handleToolExecutionError(error: unknown, toolName: string, toolCallId: string | undefined, shouldTrace: boolean, traceContext: LogContext, conversationPrivacy?: ConversationPrivacy): never;
|
|
@@ -6,6 +6,7 @@ import type { ThreadArtifactsState } from "@/chat/state/artifacts";
|
|
|
6
6
|
import type { Skill } from "@/chat/skills";
|
|
7
7
|
import type { LoadSkillMetadata } from "@/chat/tools/skill/load-skill";
|
|
8
8
|
import type { AdvisorToolRuntimeContext } from "@/chat/tools/advisor/tool";
|
|
9
|
+
import type { Requester } from "@/chat/requester";
|
|
9
10
|
export interface ImageGenerateToolDeps {
|
|
10
11
|
fetch?: typeof fetch;
|
|
11
12
|
}
|
|
@@ -56,11 +57,7 @@ export interface ToolRuntimeContext {
|
|
|
56
57
|
conversationId?: string;
|
|
57
58
|
/** Runtime-owned destination for provider-neutral side effects. */
|
|
58
59
|
destination?: Destination;
|
|
59
|
-
requester?:
|
|
60
|
-
userId?: string;
|
|
61
|
-
userName?: string;
|
|
62
|
-
fullName?: string;
|
|
63
|
-
};
|
|
60
|
+
requester?: Requester;
|
|
64
61
|
teamId?: string;
|
|
65
62
|
messageTs?: string;
|
|
66
63
|
threadTs?: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getChatConfig
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZJQPA67D.js";
|
|
4
4
|
|
|
5
5
|
// src/chat/state/adapter.ts
|
|
6
6
|
import { createMemoryState } from "@chat-adapter/state-memory";
|
|
@@ -212,6 +212,13 @@ async function getConnectedStateContext() {
|
|
|
212
212
|
stateAdapter: adapter
|
|
213
213
|
};
|
|
214
214
|
}
|
|
215
|
+
async function getDefaultRedisStateAdapterFor(adapter) {
|
|
216
|
+
if (adapter !== stateAdapter) {
|
|
217
|
+
return void 0;
|
|
218
|
+
}
|
|
219
|
+
const context = await getConnectedStateContext();
|
|
220
|
+
return context.stateAdapter === adapter ? context.redisStateAdapter : void 0;
|
|
221
|
+
}
|
|
215
222
|
function getStateAdapter() {
|
|
216
223
|
if (!stateAdapter) {
|
|
217
224
|
stateAdapter = createStateAdapter();
|
|
@@ -230,35 +237,10 @@ async function disconnectStateAdapter() {
|
|
|
230
237
|
}
|
|
231
238
|
}
|
|
232
239
|
|
|
233
|
-
// src/chat/sandbox/paths.ts
|
|
234
|
-
function normalizeWorkspaceRoot(input) {
|
|
235
|
-
const candidate = (input ?? "").trim();
|
|
236
|
-
if (!candidate) {
|
|
237
|
-
return "/vercel/sandbox";
|
|
238
|
-
}
|
|
239
|
-
const normalized = candidate.replace(/\/+$/, "");
|
|
240
|
-
return normalized.startsWith("/") ? normalized : `/${normalized}`;
|
|
241
|
-
}
|
|
242
|
-
var SANDBOX_WORKSPACE_ROOT = normalizeWorkspaceRoot(
|
|
243
|
-
process.env.VERCEL_SANDBOX_WORKSPACE_DIR
|
|
244
|
-
);
|
|
245
|
-
var SANDBOX_SKILLS_ROOT = `${SANDBOX_WORKSPACE_ROOT}/skills`;
|
|
246
|
-
var SANDBOX_DATA_ROOT = `${SANDBOX_WORKSPACE_ROOT}/data`;
|
|
247
|
-
function sandboxSkillDir(skillName) {
|
|
248
|
-
return `${SANDBOX_SKILLS_ROOT}/${skillName}`;
|
|
249
|
-
}
|
|
250
|
-
function sandboxSkillFile(skillName) {
|
|
251
|
-
return `${sandboxSkillDir(skillName)}/SKILL.md`;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
240
|
export {
|
|
255
241
|
ACTIVE_LOCK_TTL_MS,
|
|
256
242
|
getConnectedStateContext,
|
|
243
|
+
getDefaultRedisStateAdapterFor,
|
|
257
244
|
getStateAdapter,
|
|
258
|
-
disconnectStateAdapter
|
|
259
|
-
SANDBOX_WORKSPACE_ROOT,
|
|
260
|
-
SANDBOX_SKILLS_ROOT,
|
|
261
|
-
SANDBOX_DATA_ROOT,
|
|
262
|
-
sandboxSkillDir,
|
|
263
|
-
sandboxSkillFile
|
|
245
|
+
disconnectStateAdapter
|
|
264
246
|
};
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isRecord,
|
|
3
|
+
toOptionalNumber,
|
|
4
|
+
toOptionalString
|
|
5
|
+
} from "./chunk-6GEYPE6T.js";
|
|
6
|
+
|
|
7
|
+
// src/chat/state/conversation.ts
|
|
8
|
+
function coerceRole(value) {
|
|
9
|
+
return value === "assistant" || value === "system" || value === "user" ? value : "user";
|
|
10
|
+
}
|
|
11
|
+
function coerceAuthor(value) {
|
|
12
|
+
if (!isRecord(value)) return void 0;
|
|
13
|
+
const author = {
|
|
14
|
+
fullName: toOptionalString(value.fullName),
|
|
15
|
+
userId: toOptionalString(value.userId),
|
|
16
|
+
userName: toOptionalString(value.userName)
|
|
17
|
+
};
|
|
18
|
+
if (typeof value.isBot === "boolean") {
|
|
19
|
+
author.isBot = value.isBot;
|
|
20
|
+
}
|
|
21
|
+
if (!author.fullName && !author.userId && !author.userName && author.isBot === void 0) {
|
|
22
|
+
return void 0;
|
|
23
|
+
}
|
|
24
|
+
return author;
|
|
25
|
+
}
|
|
26
|
+
function coerceMessageMeta(value) {
|
|
27
|
+
if (!isRecord(value)) return void 0;
|
|
28
|
+
const meta = {};
|
|
29
|
+
const attachmentCount = toOptionalNumber(value.attachmentCount);
|
|
30
|
+
if (typeof attachmentCount === "number" && attachmentCount > 0) {
|
|
31
|
+
meta.attachmentCount = attachmentCount;
|
|
32
|
+
}
|
|
33
|
+
if (typeof value.explicitMention === "boolean") {
|
|
34
|
+
meta.explicitMention = value.explicitMention;
|
|
35
|
+
}
|
|
36
|
+
const imageAttachmentCount = toOptionalNumber(value.imageAttachmentCount);
|
|
37
|
+
if (typeof imageAttachmentCount === "number" && imageAttachmentCount > 0) {
|
|
38
|
+
meta.imageAttachmentCount = imageAttachmentCount;
|
|
39
|
+
}
|
|
40
|
+
if (typeof value.replied === "boolean") {
|
|
41
|
+
meta.replied = value.replied;
|
|
42
|
+
}
|
|
43
|
+
if (typeof value.skippedReason === "string" && value.skippedReason.trim().length > 0) {
|
|
44
|
+
meta.skippedReason = value.skippedReason;
|
|
45
|
+
}
|
|
46
|
+
if (typeof value.slackTs === "string" && value.slackTs.trim().length > 0) {
|
|
47
|
+
meta.slackTs = value.slackTs;
|
|
48
|
+
}
|
|
49
|
+
if (Array.isArray(value.imageFileIds)) {
|
|
50
|
+
const imageFileIds = value.imageFileIds.filter(
|
|
51
|
+
(entry) => typeof entry === "string" && entry.trim().length > 0
|
|
52
|
+
);
|
|
53
|
+
if (imageFileIds.length > 0) {
|
|
54
|
+
meta.imageFileIds = imageFileIds;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
if (typeof value.imagesHydrated === "boolean") {
|
|
58
|
+
meta.imagesHydrated = value.imagesHydrated;
|
|
59
|
+
}
|
|
60
|
+
if (meta.attachmentCount === void 0 && meta.explicitMention === void 0 && meta.imageAttachmentCount === void 0 && meta.replied === void 0 && meta.skippedReason === void 0 && meta.slackTs === void 0 && meta.imageFileIds === void 0 && meta.imagesHydrated === void 0) {
|
|
61
|
+
return void 0;
|
|
62
|
+
}
|
|
63
|
+
return meta;
|
|
64
|
+
}
|
|
65
|
+
function defaultConversationState() {
|
|
66
|
+
const nowMs = Date.now();
|
|
67
|
+
return {
|
|
68
|
+
schemaVersion: 1,
|
|
69
|
+
messages: [],
|
|
70
|
+
piMessages: [],
|
|
71
|
+
compactions: [],
|
|
72
|
+
backfill: {},
|
|
73
|
+
processing: {},
|
|
74
|
+
stats: {
|
|
75
|
+
estimatedContextTokens: 0,
|
|
76
|
+
totalMessageCount: 0,
|
|
77
|
+
compactedMessageCount: 0,
|
|
78
|
+
updatedAtMs: nowMs
|
|
79
|
+
},
|
|
80
|
+
vision: {
|
|
81
|
+
byFileId: {}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function coercePendingAuthState(value) {
|
|
86
|
+
if (!isRecord(value)) {
|
|
87
|
+
return void 0;
|
|
88
|
+
}
|
|
89
|
+
const kind = value.kind;
|
|
90
|
+
const provider = toOptionalString(value.provider);
|
|
91
|
+
const requesterId = toOptionalString(value.requesterId);
|
|
92
|
+
const scope = toOptionalString(value.scope);
|
|
93
|
+
const sessionId = toOptionalString(value.sessionId);
|
|
94
|
+
const linkSentAtMs = toOptionalNumber(value.linkSentAtMs);
|
|
95
|
+
if (kind !== "mcp" && kind !== "plugin" || !provider || !requesterId || !sessionId || typeof linkSentAtMs !== "number") {
|
|
96
|
+
return void 0;
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
kind,
|
|
100
|
+
provider,
|
|
101
|
+
requesterId,
|
|
102
|
+
...scope ? { scope } : {},
|
|
103
|
+
sessionId,
|
|
104
|
+
linkSentAtMs
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
function coerceThreadConversationState(value) {
|
|
108
|
+
if (!isRecord(value)) {
|
|
109
|
+
return defaultConversationState();
|
|
110
|
+
}
|
|
111
|
+
const root = value;
|
|
112
|
+
const rawConversation = isRecord(root.conversation) ? root.conversation : {};
|
|
113
|
+
const base = defaultConversationState();
|
|
114
|
+
const rawMessages = Array.isArray(rawConversation.messages) ? rawConversation.messages : [];
|
|
115
|
+
const messages = [];
|
|
116
|
+
for (const item of rawMessages) {
|
|
117
|
+
if (!isRecord(item)) continue;
|
|
118
|
+
const id = toOptionalString(item.id);
|
|
119
|
+
const text = toOptionalString(item.text);
|
|
120
|
+
const createdAtMs = toOptionalNumber(item.createdAtMs);
|
|
121
|
+
if (!id || !text || !createdAtMs) continue;
|
|
122
|
+
messages.push({
|
|
123
|
+
id,
|
|
124
|
+
role: coerceRole(item.role),
|
|
125
|
+
text,
|
|
126
|
+
createdAtMs,
|
|
127
|
+
author: coerceAuthor(item.author),
|
|
128
|
+
meta: coerceMessageMeta(item.meta)
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
const rawCompactions = Array.isArray(rawConversation.compactions) ? rawConversation.compactions : [];
|
|
132
|
+
const compactions = [];
|
|
133
|
+
for (const item of rawCompactions) {
|
|
134
|
+
if (!isRecord(item)) continue;
|
|
135
|
+
const id = toOptionalString(item.id);
|
|
136
|
+
const summary = toOptionalString(item.summary);
|
|
137
|
+
const createdAtMs = toOptionalNumber(item.createdAtMs);
|
|
138
|
+
if (!id || !summary || !createdAtMs) continue;
|
|
139
|
+
const coveredMessageIds = Array.isArray(item.coveredMessageIds) ? item.coveredMessageIds.filter(
|
|
140
|
+
(entry) => typeof entry === "string" && entry.length > 0
|
|
141
|
+
) : [];
|
|
142
|
+
compactions.push({
|
|
143
|
+
id,
|
|
144
|
+
summary,
|
|
145
|
+
createdAtMs,
|
|
146
|
+
coveredMessageIds
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
const rawBackfill = isRecord(rawConversation.backfill) ? rawConversation.backfill : {};
|
|
150
|
+
const backfill = {
|
|
151
|
+
completedAtMs: toOptionalNumber(rawBackfill.completedAtMs),
|
|
152
|
+
source: rawBackfill.source === "recent_messages" || rawBackfill.source === "thread_fetch" ? rawBackfill.source : void 0
|
|
153
|
+
};
|
|
154
|
+
const rawProcessing = isRecord(rawConversation.processing) ? rawConversation.processing : {};
|
|
155
|
+
const processing = {
|
|
156
|
+
activeTurnId: toOptionalString(rawProcessing.activeTurnId),
|
|
157
|
+
lastCompletedAtMs: toOptionalNumber(rawProcessing.lastCompletedAtMs),
|
|
158
|
+
pendingAuth: coercePendingAuthState(rawProcessing.pendingAuth)
|
|
159
|
+
};
|
|
160
|
+
const rawStats = isRecord(rawConversation.stats) ? rawConversation.stats : {};
|
|
161
|
+
const stats = {
|
|
162
|
+
estimatedContextTokens: toOptionalNumber(rawStats.estimatedContextTokens) ?? base.stats.estimatedContextTokens,
|
|
163
|
+
totalMessageCount: toOptionalNumber(rawStats.totalMessageCount) ?? messages.length,
|
|
164
|
+
compactedMessageCount: toOptionalNumber(rawStats.compactedMessageCount) ?? 0,
|
|
165
|
+
updatedAtMs: toOptionalNumber(rawStats.updatedAtMs) ?? base.stats.updatedAtMs
|
|
166
|
+
};
|
|
167
|
+
const rawVision = isRecord(rawConversation.vision) ? rawConversation.vision : {};
|
|
168
|
+
const rawVisionByFileId = isRecord(rawVision.byFileId) ? rawVision.byFileId : {};
|
|
169
|
+
const byFileId = {};
|
|
170
|
+
for (const [fileId, value2] of Object.entries(rawVisionByFileId)) {
|
|
171
|
+
if (typeof fileId !== "string" || fileId.trim().length === 0) continue;
|
|
172
|
+
if (!isRecord(value2)) continue;
|
|
173
|
+
const summary = toOptionalString(value2.summary);
|
|
174
|
+
const analyzedAtMs = toOptionalNumber(value2.analyzedAtMs);
|
|
175
|
+
if (!summary || !analyzedAtMs) continue;
|
|
176
|
+
byFileId[fileId] = {
|
|
177
|
+
summary,
|
|
178
|
+
analyzedAtMs
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
schemaVersion: 1,
|
|
183
|
+
messages,
|
|
184
|
+
piMessages: Array.isArray(rawConversation.piMessages) ? rawConversation.piMessages : [],
|
|
185
|
+
compactions,
|
|
186
|
+
backfill,
|
|
187
|
+
processing,
|
|
188
|
+
stats,
|
|
189
|
+
vision: {
|
|
190
|
+
backfillCompletedAtMs: toOptionalNumber(rawVision.backfillCompletedAtMs),
|
|
191
|
+
byFileId
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function buildConversationStatePatch(conversation) {
|
|
196
|
+
return {
|
|
197
|
+
conversation: {
|
|
198
|
+
...conversation,
|
|
199
|
+
schemaVersion: 1,
|
|
200
|
+
stats: {
|
|
201
|
+
...conversation.stats,
|
|
202
|
+
totalMessageCount: conversation.messages.length,
|
|
203
|
+
updatedAtMs: Date.now()
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export {
|
|
210
|
+
coerceThreadConversationState,
|
|
211
|
+
buildConversationStatePatch
|
|
212
|
+
};
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getPluginForSkillPath,
|
|
3
3
|
getPluginSkillRoots
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-GB3AL54K.js";
|
|
5
5
|
import {
|
|
6
|
-
logWarn,
|
|
7
6
|
skillRoots
|
|
8
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-KVZL5NZS.js";
|
|
8
|
+
import {
|
|
9
|
+
logWarn
|
|
10
|
+
} from "./chunk-6GEYPE6T.js";
|
|
9
11
|
|
|
10
12
|
// src/chat/skills.ts
|
|
11
13
|
import fs from "fs/promises";
|