@code-yeongyu/senpi 2026.9.11 → 2026.9.12-2
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/CHANGELOG.md +40 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +5 -1
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +13 -9
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +54 -121
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/cursor-history-admission.d.ts +50 -0
- package/dist/core/cursor-history-admission.d.ts.map +1 -0
- package/dist/core/cursor-history-admission.js +130 -0
- package/dist/core/cursor-history-admission.js.map +1 -0
- package/dist/core/extensions/builtin/cursor-cli-oauth/models.d.ts.map +1 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/models.js +2 -1
- package/dist/core/extensions/builtin/cursor-cli-oauth/models.js.map +1 -1
- package/dist/core/session-manager.d.ts +2 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +22 -13
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-write-reservation.d.ts +9 -0
- package/dist/core/session-write-reservation.d.ts.map +1 -1
- package/dist/core/session-write-reservation.js +33 -0
- package/dist/core/session-write-reservation.js.map +1 -1
- package/dist/modes/interactive/components/ask-user-async-widget.d.ts +2 -0
- package/dist/modes/interactive/components/ask-user-async-widget.d.ts.map +1 -1
- package/dist/modes/interactive/components/ask-user-async-widget.js +17 -1
- package/dist/modes/interactive/components/ask-user-async-widget.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +2 -2
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +2 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js +1 -0
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-path-reservations.d.ts +30 -0
- package/dist/modes/rpc/session-path-reservations.d.ts.map +1 -0
- package/dist/modes/rpc/session-path-reservations.js +58 -0
- package/dist/modes/rpc/session-path-reservations.js.map +1 -0
- package/dist/modes/rpc/session-registry.d.ts +3 -1
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/dist/modes/rpc/session-worker-client.d.ts +10 -8
- package/dist/modes/rpc/session-worker-client.d.ts.map +1 -1
- package/dist/modes/rpc/session-worker-client.js +14 -23
- package/dist/modes/rpc/session-worker-client.js.map +1 -1
- package/dist/modes/rpc/session-worker-credit.d.ts +17 -0
- package/dist/modes/rpc/session-worker-credit.d.ts.map +1 -0
- package/dist/modes/rpc/session-worker-credit.js +39 -0
- package/dist/modes/rpc/session-worker-credit.js.map +1 -0
- package/dist/modes/rpc/session-worker-protocol.d.ts +10 -0
- package/dist/modes/rpc/session-worker-protocol.d.ts.map +1 -1
- package/dist/modes/rpc/session-worker-protocol.js +2 -0
- package/dist/modes/rpc/session-worker-protocol.js.map +1 -1
- package/dist/modes/rpc/session-worker-signals.d.ts +7 -0
- package/dist/modes/rpc/session-worker-signals.d.ts.map +1 -0
- package/dist/modes/rpc/session-worker-signals.js +19 -0
- package/dist/modes/rpc/session-worker-signals.js.map +1 -0
- package/dist/modes/rpc/session-worker.js +12 -16
- package/dist/modes/rpc/session-worker.js.map +1 -1
- package/dist/modes/rpc/worker-session-registry.d.ts +12 -0
- package/dist/modes/rpc/worker-session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/worker-session-registry.js +51 -24
- package/dist/modes/rpc/worker-session-registry.js.map +1 -1
- package/docs/rpc.md +14 -6
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts +11 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js +18 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent/measure.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js +5 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/cursor-agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.d.ts +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.js +96 -51
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/discovery.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.d.ts +389 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.js +132 -4
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/gen/cascade_pb.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.d.ts +34 -4
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.js +41 -8
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/metadata.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.d.ts +20 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.js +20 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/paths.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.d.ts +18 -6
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.js +77 -35
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/request.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.d.ts +9 -3
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.js +30 -38
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/stream-state.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/trailer.d.ts +16 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/trailer.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/trailer.js +69 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/trailer.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/unary.d.ts +26 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/unary.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/unary.js +61 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/unary.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.d.ts +6 -4
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.js +6 -4
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent/wire.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.d.ts +13 -5
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.js +76 -21
- package/node_modules/@earendil-works/pi-ai/dist/api/devin-agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.js +7 -2
- package/node_modules/@earendil-works/pi-ai/dist/auth/oauth/devin.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/context-limit-store.d.ts +32 -0
- package/node_modules/@earendil-works/pi-ai/dist/cursor/context-limit-store.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/cursor/context-limit-store.js +62 -0
- package/node_modules/@earendil-works/pi-ai/dist/cursor/context-limit-store.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/cursor/store-migration.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/model.d.ts +11 -1
- package/node_modules/@earendil-works/pi-ai/dist/model.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/model.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.js +2 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/cursor.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/amazon-bedrock.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/venice.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.js +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts +4 -2
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js +18 -9
- package/node_modules/@earendil-works/pi-ai/dist/providers/devin.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/cursor-context-limit.d.ts +12 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/cursor-context-limit.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/cursor-context-limit.js +93 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/cursor-context-limit.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
|
@@ -11,6 +11,26 @@
|
|
|
11
11
|
export const DEVIN_DEFAULT_BASE_URL = "https://server.codeium.com";
|
|
12
12
|
export const DEVIN_CHAT_MESSAGE_PATH = "/exa.api_server_pb.ApiServerService/GetChatMessage";
|
|
13
13
|
export const DEVIN_CLI_MODEL_CONFIGS_PATH = "/exa.api_server_pb.ApiServerService/GetCliModelConfigs";
|
|
14
|
+
export const DEVIN_ASSIGN_MODEL_PATH = "/exa.api_server_pb.ApiServerService/AssignModel";
|
|
15
|
+
export const DEVIN_USER_JWT_PATH = "/exa.auth_pb.AuthService/GetUserJwt";
|
|
16
|
+
/**
|
|
17
|
+
* Request headers the released CLI sends on the streaming chat call. Auth rides
|
|
18
|
+
* inside `Metadata.api_key`, so there is no `authorization` header.
|
|
19
|
+
*/
|
|
20
|
+
export const DEVIN_CHAT_HEADERS = {
|
|
21
|
+
"content-type": "application/connect+proto",
|
|
22
|
+
"connect-protocol-version": "1",
|
|
23
|
+
"connect-content-encoding": "gzip",
|
|
24
|
+
"accept-encoding": "identity",
|
|
25
|
+
"user-agent": "connect-go/1.18.1 (go1.26.3)",
|
|
26
|
+
"connect-accept-encoding": "gzip",
|
|
27
|
+
};
|
|
28
|
+
/** Unary Connect calls carry a bare protobuf body, not the 5-byte streaming frame. */
|
|
29
|
+
export const DEVIN_UNARY_HEADERS = {
|
|
30
|
+
"content-type": "application/proto",
|
|
31
|
+
"connect-protocol-version": "1",
|
|
32
|
+
accept: "*/*",
|
|
33
|
+
};
|
|
14
34
|
/** Connect frame flags: bit 0 marks a gzipped payload, bit 1 the end-of-stream trailer. */
|
|
15
35
|
export const DEVIN_COMPRESSED_FLAG = 0x01;
|
|
16
36
|
export const DEVIN_TRAILER_FLAG = 0x02;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/api/devin-agent/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AACnE,MAAM,CAAC,MAAM,uBAAuB,GAAG,oDAAoD,CAAC;AAC5F,MAAM,CAAC,MAAM,4BAA4B,GAAG,wDAAwD,CAAC;
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../../src/api/devin-agent/paths.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAAG,4BAA4B,CAAC;AACnE,MAAM,CAAC,MAAM,uBAAuB,GAAG,oDAAoD,CAAC;AAC5F,MAAM,CAAC,MAAM,4BAA4B,GAAG,wDAAwD,CAAC;AACrG,MAAM,CAAC,MAAM,uBAAuB,GAAG,iDAAiD,CAAC;AACzF,MAAM,CAAC,MAAM,mBAAmB,GAAG,qCAAqC,CAAC;AAEzE;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IACjC,cAAc,EAAE,2BAA2B;IAC3C,0BAA0B,EAAE,GAAG;IAC/B,0BAA0B,EAAE,MAAM;IAClC,iBAAiB,EAAE,UAAU;IAC7B,YAAY,EAAE,8BAA8B;IAC5C,yBAAyB,EAAE,MAAM;CACxB,CAAC;AAEX,sFAAsF;AACtF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAClC,cAAc,EAAE,mBAAmB;IACnC,0BAA0B,EAAE,GAAG;IAC/B,MAAM,EAAE,KAAK;CACJ,CAAC;AAEX,2FAA2F;AAC3F,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC;AAC1C,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC;;;;GAIG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC","sourcesContent":["/**\n * Cascade RPC paths and wire constants.\n *\n * Devin's released CLI speaks the Connect protocol over HTTP/1.1 against\n * Codeium's Cascade edge. The service paths are spelled out here rather than\n * derived from a generated service descriptor: the vendored schema in\n * packages/ai/proto/devin/cascade.proto carries only the message subset the\n * transport needs, so its package name is cosmetic while these paths are the\n * real contract.\n */\n\nexport const DEVIN_DEFAULT_BASE_URL = \"https://server.codeium.com\";\nexport const DEVIN_CHAT_MESSAGE_PATH = \"/exa.api_server_pb.ApiServerService/GetChatMessage\";\nexport const DEVIN_CLI_MODEL_CONFIGS_PATH = \"/exa.api_server_pb.ApiServerService/GetCliModelConfigs\";\nexport const DEVIN_ASSIGN_MODEL_PATH = \"/exa.api_server_pb.ApiServerService/AssignModel\";\nexport const DEVIN_USER_JWT_PATH = \"/exa.auth_pb.AuthService/GetUserJwt\";\n\n/**\n * Request headers the released CLI sends on the streaming chat call. Auth rides\n * inside `Metadata.api_key`, so there is no `authorization` header.\n */\nexport const DEVIN_CHAT_HEADERS = {\n\t\"content-type\": \"application/connect+proto\",\n\t\"connect-protocol-version\": \"1\",\n\t\"connect-content-encoding\": \"gzip\",\n\t\"accept-encoding\": \"identity\",\n\t\"user-agent\": \"connect-go/1.18.1 (go1.26.3)\",\n\t\"connect-accept-encoding\": \"gzip\",\n} as const;\n\n/** Unary Connect calls carry a bare protobuf body, not the 5-byte streaming frame. */\nexport const DEVIN_UNARY_HEADERS = {\n\t\"content-type\": \"application/proto\",\n\t\"connect-protocol-version\": \"1\",\n\taccept: \"*/*\",\n} as const;\n\n/** Connect frame flags: bit 0 marks a gzipped payload, bit 1 the end-of-stream trailer. */\nexport const DEVIN_COMPRESSED_FLAG = 0x01;\nexport const DEVIN_TRAILER_FLAG = 0x02;\n\n/**\n * Hard upper bound on one Connect frame payload. The 4-byte length prefix can\n * describe 4 GiB; a corrupted or hostile prefix must not turn into an\n * allocation of that size, so anything larger is a protocol error.\n */\nexport const DEVIN_MAX_FRAME_PAYLOAD = 64 * 1024 * 1024;\n"]}
|
|
@@ -4,21 +4,33 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Cascade has no system role: the system prompt travels in the top-level
|
|
6
6
|
* `prompt` field, and history is a flat list of `ChatMessagePrompt` entries
|
|
7
|
-
* whose `source` carries the role. Message ids
|
|
8
|
-
* from the conversation id and the entry index so a
|
|
9
|
-
* same ids instead of forking the server-side
|
|
7
|
+
* whose `source` carries the role. Message ids must be UUID-shaped; they are
|
|
8
|
+
* derived deterministically from the conversation id and the entry index so a
|
|
9
|
+
* retried turn re-sends the same ids instead of forking the server-side
|
|
10
|
+
* transcript, while a native Devin turn is replayed under the id the server
|
|
11
|
+
* minted for it.
|
|
10
12
|
*/
|
|
11
|
-
import type { Context, Model } from "../../types.ts";
|
|
12
|
-
import { type GetChatMessageRequest } from "./gen/cascade_pb.ts";
|
|
13
|
+
import type { Context, Message, Model } from "../../types.ts";
|
|
14
|
+
import { type ChatMessagePrompt, type GetChatMessageRequest } from "./gen/cascade_pb.ts";
|
|
13
15
|
/** Cascade's own stop vocabulary; the server echoes these as STOP_PATTERN. */
|
|
14
16
|
export declare const DEVIN_DEFAULT_STOP_PATTERNS: readonly ["<|user|>", "<|bot|>", "<|context_request|>", "<|endoftext|>", "<|end_of_turn|>"];
|
|
17
|
+
export interface DevinModelAssignment {
|
|
18
|
+
modelUid: string;
|
|
19
|
+
assignmentJwt: string;
|
|
20
|
+
}
|
|
15
21
|
export interface DevinChatRequestInput {
|
|
16
22
|
model: Model<"devin-agent">;
|
|
17
23
|
context: Context;
|
|
18
24
|
apiKey: string | undefined;
|
|
19
|
-
|
|
25
|
+
userJwt?: string;
|
|
26
|
+
cascadeId: string;
|
|
27
|
+
assignment?: DevinModelAssignment;
|
|
20
28
|
maxTokens?: number;
|
|
21
29
|
temperature?: number;
|
|
30
|
+
topP?: number;
|
|
31
|
+
stopSequences?: readonly string[];
|
|
22
32
|
}
|
|
23
33
|
export declare function buildDevinChatRequest(input: DevinChatRequestInput): GetChatMessageRequest;
|
|
34
|
+
/** The router scores the latest user turn alone; the chat request mints the turn's id. */
|
|
35
|
+
export declare function buildDevinRouterPrompt(messages: readonly Message[]): ChatMessagePrompt | undefined;
|
|
24
36
|
//# sourceMappingURL=request.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/api/devin-agent/request.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/api/devin-agent/request.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAQ,MAAM,gBAAgB,CAAC;AAEpE,OAAO,EAEN,KAAK,iBAAiB,EAQtB,KAAK,qBAAqB,EAK1B,MAAM,qBAAqB,CAAC;AAG7B,8EAA8E;AAC9E,eAAO,MAAM,2BAA2B,YACvC,UAAU,EACV,SAAS,EACT,qBAAqB,EACrB,eAAe,EACf,iBAAiB,CACR,CAAC;AAOX,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACrC,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAMD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,qBAAqB,GAAG,qBAAqB,CA6BzF;AAED,0FAA0F;AAC1F,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,iBAAiB,GAAG,SAAS,CAMlG"}
|
|
@@ -4,12 +4,15 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Cascade has no system role: the system prompt travels in the top-level
|
|
6
6
|
* `prompt` field, and history is a flat list of `ChatMessagePrompt` entries
|
|
7
|
-
* whose `source` carries the role. Message ids
|
|
8
|
-
* from the conversation id and the entry index so a
|
|
9
|
-
* same ids instead of forking the server-side
|
|
7
|
+
* whose `source` carries the role. Message ids must be UUID-shaped; they are
|
|
8
|
+
* derived deterministically from the conversation id and the entry index so a
|
|
9
|
+
* retried turn re-sends the same ids instead of forking the server-side
|
|
10
|
+
* transcript, while a native Devin turn is replayed under the id the server
|
|
11
|
+
* minted for it.
|
|
10
12
|
*/
|
|
11
13
|
import { create } from "@bufbuild/protobuf";
|
|
12
|
-
import {
|
|
14
|
+
import { deterministicUuid } from "../cursor-agent/deterministic-id.js";
|
|
15
|
+
import { CacheControlType, ChatMessagePromptSchema, ChatMessageRequestType, ChatMessageSource, ChatToolCallSchema, ChatToolDefinitionSchema, CompletionConfigurationSchema, ConversationalPlannerMode, GetChatMessageRequestSchema, ImageDataSchema, PromptCacheOptionsSchema, } from "./gen/cascade_pb.js";
|
|
13
16
|
import { devinCliMetadata } from "./metadata.js";
|
|
14
17
|
/** Cascade's own stop vocabulary; the server echoes these as STOP_PATTERN. */
|
|
15
18
|
export const DEVIN_DEFAULT_STOP_PATTERNS = [
|
|
@@ -19,66 +22,95 @@ export const DEVIN_DEFAULT_STOP_PATTERNS = [
|
|
|
19
22
|
"<|endoftext|>",
|
|
20
23
|
"<|end_of_turn|>",
|
|
21
24
|
];
|
|
25
|
+
const DEFAULT_MAX_TOKENS = 64_000;
|
|
26
|
+
const DEFAULT_TEMPERATURE = 0.4;
|
|
27
|
+
/** Cascade refuses a temperature of exactly 0 (proto3 drops it) with an opaque invalid_argument. */
|
|
28
|
+
const MIN_TEMPERATURE = 0.0001;
|
|
22
29
|
export function buildDevinChatRequest(input) {
|
|
23
|
-
const
|
|
30
|
+
const temperature = Math.max(input.temperature ?? DEFAULT_TEMPERATURE, MIN_TEMPERATURE);
|
|
31
|
+
const stopPatterns = [...DEVIN_DEFAULT_STOP_PATTERNS, ...(input.stopSequences ?? [])];
|
|
24
32
|
return create(GetChatMessageRequestSchema, {
|
|
25
|
-
metadata: devinCliMetadata(input.apiKey),
|
|
33
|
+
metadata: devinCliMetadata(input.apiKey, input.userJwt ?? ""),
|
|
26
34
|
prompt: input.context.systemPrompt ?? "",
|
|
27
|
-
chatMessagePrompts: mapHistory(input.context.messages, cascadeId),
|
|
35
|
+
chatMessagePrompts: mapHistory(input.context.messages, input.cascadeId, input.model),
|
|
28
36
|
requestType: ChatMessageRequestType.CASCADE,
|
|
29
37
|
plannerMode: ConversationalPlannerMode.DEFAULT,
|
|
30
|
-
chatModelUid: input.model.id,
|
|
31
|
-
|
|
32
|
-
cascadeId,
|
|
38
|
+
chatModelUid: input.assignment?.modelUid ?? input.model.upstreamModelId ?? input.model.id,
|
|
39
|
+
...(input.assignment ? { modelAssignmentJwt: input.assignment.assignmentJwt } : {}),
|
|
40
|
+
cascadeId: input.cascadeId,
|
|
41
|
+
executionId: crypto.randomUUID(),
|
|
33
42
|
tools: (input.context.tools ?? []).map(toolDefinition),
|
|
34
43
|
toolChoice: { choice: { case: "optionName", value: "auto" } },
|
|
35
44
|
systemPromptCacheOptions: create(PromptCacheOptionsSchema, { type: CacheControlType.EPHEMERAL }),
|
|
45
|
+
disableParallelToolCalls: input.model.compat?.supportsParallelToolCalls !== true,
|
|
36
46
|
configuration: create(CompletionConfigurationSchema, {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
numCompletions: 1n,
|
|
48
|
+
maxTokens: BigInt(input.maxTokens ?? input.model.maxTokens ?? DEFAULT_MAX_TOKENS),
|
|
49
|
+
maxNewlines: 200n,
|
|
50
|
+
temperature,
|
|
51
|
+
firstTemperature: temperature,
|
|
52
|
+
topK: 50n,
|
|
53
|
+
topP: input.topP ?? 1,
|
|
54
|
+
stopPatterns,
|
|
55
|
+
fimEotProbThreshold: 1,
|
|
40
56
|
}),
|
|
41
57
|
});
|
|
42
58
|
}
|
|
59
|
+
/** The router scores the latest user turn alone; the chat request mints the turn's id. */
|
|
60
|
+
export function buildDevinRouterPrompt(messages) {
|
|
61
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
62
|
+
const message = messages[index];
|
|
63
|
+
if (message?.role === "user")
|
|
64
|
+
return userPrompt(message, "");
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
43
68
|
function toolDefinition(tool) {
|
|
44
69
|
return create(ChatToolDefinitionSchema, {
|
|
45
70
|
name: tool.name,
|
|
46
71
|
description: tool.description,
|
|
47
72
|
jsonSchemaString: JSON.stringify(tool.parameters ?? {}),
|
|
73
|
+
strict: false,
|
|
48
74
|
});
|
|
49
75
|
}
|
|
50
|
-
function mapHistory(messages, cascadeId) {
|
|
76
|
+
function mapHistory(messages, cascadeId, model) {
|
|
51
77
|
const prompts = [];
|
|
52
78
|
for (const [index, message] of messages.entries()) {
|
|
53
|
-
const
|
|
79
|
+
const seed = `${cascadeId}\u0000${index}\u0000${message.role}`;
|
|
54
80
|
if (message.role === "user")
|
|
55
|
-
prompts.push(userPrompt(message
|
|
56
|
-
else if (message.role === "assistant")
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
81
|
+
prompts.push(userPrompt(message, deterministicUuid(seed)));
|
|
82
|
+
else if (message.role === "assistant") {
|
|
83
|
+
const prompt = assistantPrompt(message, model, `bot-${deterministicUuid(seed)}`);
|
|
84
|
+
if (prompt)
|
|
85
|
+
prompts.push(prompt);
|
|
86
|
+
}
|
|
87
|
+
else if (message.role === "toolResult") {
|
|
88
|
+
prompts.push(toolResultPrompt(message, deterministicUuid(`${seed}\u0000${message.toolCallId}`)));
|
|
89
|
+
}
|
|
60
90
|
}
|
|
61
91
|
return prompts;
|
|
62
92
|
}
|
|
63
|
-
function userPrompt(
|
|
64
|
-
const text = typeof content === "string" ?
|
|
93
|
+
function userPrompt(message, messageId) {
|
|
94
|
+
const { text, images } = splitContent(typeof message.content === "string" ? [] : message.content);
|
|
65
95
|
return create(ChatMessagePromptSchema, {
|
|
66
96
|
messageId,
|
|
67
97
|
source: ChatMessageSource.USER,
|
|
68
|
-
prompt: text,
|
|
98
|
+
prompt: typeof message.content === "string" ? message.content : text,
|
|
99
|
+
images,
|
|
69
100
|
});
|
|
70
101
|
}
|
|
71
|
-
function assistantPrompt(message,
|
|
72
|
-
const
|
|
102
|
+
function assistantPrompt(message, model, fallbackId) {
|
|
103
|
+
const native = message.api === model.api && message.provider === model.provider && message.model === model.id;
|
|
104
|
+
let text = "";
|
|
73
105
|
let thinking = "";
|
|
74
106
|
let signature = "";
|
|
75
107
|
const toolCalls = [];
|
|
76
108
|
for (const block of message.content) {
|
|
77
109
|
if (block.type === "text")
|
|
78
|
-
text
|
|
110
|
+
text += block.text;
|
|
79
111
|
else if (block.type === "thinking") {
|
|
80
112
|
thinking += block.thinking;
|
|
81
|
-
if (block.thinkingSignature)
|
|
113
|
+
if (native && !signature && block.thinkingSignature)
|
|
82
114
|
signature = block.thinkingSignature;
|
|
83
115
|
}
|
|
84
116
|
else if (block.type === "toolCall") {
|
|
@@ -89,28 +121,38 @@ function assistantPrompt(message, messageId) {
|
|
|
89
121
|
}));
|
|
90
122
|
}
|
|
91
123
|
}
|
|
124
|
+
if (!text && !thinking && !signature && toolCalls.length === 0)
|
|
125
|
+
return undefined;
|
|
92
126
|
return create(ChatMessagePromptSchema, {
|
|
93
|
-
messageId,
|
|
127
|
+
messageId: native && message.responseId ? message.responseId : fallbackId,
|
|
94
128
|
source: ChatMessageSource.SYSTEM,
|
|
95
|
-
prompt: text
|
|
129
|
+
prompt: text,
|
|
96
130
|
thinking,
|
|
97
131
|
signature,
|
|
132
|
+
signatureType: "",
|
|
98
133
|
toolCalls,
|
|
99
134
|
});
|
|
100
135
|
}
|
|
101
136
|
function toolResultPrompt(message, messageId) {
|
|
137
|
+
const { text, images } = splitContent(message.content);
|
|
102
138
|
return create(ChatMessagePromptSchema, {
|
|
103
139
|
messageId,
|
|
104
140
|
source: ChatMessageSource.TOOL,
|
|
105
|
-
prompt:
|
|
141
|
+
prompt: text,
|
|
142
|
+
images,
|
|
106
143
|
toolCallId: message.toolCallId,
|
|
107
144
|
toolResultIsError: message.isError === true,
|
|
108
145
|
});
|
|
109
146
|
}
|
|
110
|
-
function
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
.
|
|
147
|
+
function splitContent(content) {
|
|
148
|
+
let text = "";
|
|
149
|
+
const images = [];
|
|
150
|
+
for (const block of content) {
|
|
151
|
+
if (block.type === "text")
|
|
152
|
+
text += block.text;
|
|
153
|
+
else
|
|
154
|
+
images.push(create(ImageDataSchema, { base64Data: block.data, mimeType: block.mimeType }));
|
|
155
|
+
}
|
|
156
|
+
return { text, images };
|
|
115
157
|
}
|
|
116
158
|
//# sourceMappingURL=request.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../../src/api/devin-agent/request.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Builds the Cascade `GetChatMessage` request from senpi's provider-neutral\n * context.\n *\n * Cascade has no system role: the system prompt travels in the top-level\n * `prompt` field, and history is a flat list of `ChatMessagePrompt` entries\n * whose `source` carries the role. Message ids are derived deterministically\n * from the conversation id and the entry index so a retried turn re-sends the\n * same ids instead of forking the server-side transcript.\n */\n\nimport { create } from \"@bufbuild/protobuf\";\nimport type { Context, Message, Model, Tool } from \"../../types.ts\";\nimport {\n\tCacheControlType,\n\ttype ChatMessagePrompt,\n\tChatMessagePromptSchema,\n\tChatMessageRequestType,\n\tChatMessageSource,\n\tChatToolCallSchema,\n\tChatToolDefinitionSchema,\n\tCompletionConfigurationSchema,\n\tConversationalPlannerMode,\n\ttype GetChatMessageRequest,\n\tGetChatMessageRequestSchema,\n\tPromptCacheOptionsSchema,\n} from \"./gen/cascade_pb.ts\";\nimport { devinCliMetadata } from \"./metadata.ts\";\n\n/** Cascade's own stop vocabulary; the server echoes these as STOP_PATTERN. */\nexport const DEVIN_DEFAULT_STOP_PATTERNS = [\n\t\"<|user|>\",\n\t\"<|bot|>\",\n\t\"<|context_request|>\",\n\t\"<|endoftext|>\",\n\t\"<|end_of_turn|>\",\n] as const;\n\nexport interface DevinChatRequestInput {\n\tmodel: Model<\"devin-agent\">;\n\tcontext: Context;\n\tapiKey: string | undefined;\n\tcascadeId?: string;\n\tmaxTokens?: number;\n\ttemperature?: number;\n}\n\nexport function buildDevinChatRequest(input: DevinChatRequestInput): GetChatMessageRequest {\n\tconst cascadeId = input.cascadeId ?? \"\";\n\treturn create(GetChatMessageRequestSchema, {\n\t\tmetadata: devinCliMetadata(input.apiKey),\n\t\tprompt: input.context.systemPrompt ?? \"\",\n\t\tchatMessagePrompts: mapHistory(input.context.messages, cascadeId),\n\t\trequestType: ChatMessageRequestType.CASCADE,\n\t\tplannerMode: ConversationalPlannerMode.DEFAULT,\n\t\tchatModelUid: input.model.id,\n\t\tchatModelName: input.model.name ?? input.model.id,\n\t\tcascadeId,\n\t\ttools: (input.context.tools ?? []).map(toolDefinition),\n\t\ttoolChoice: { choice: { case: \"optionName\", value: \"auto\" } },\n\t\tsystemPromptCacheOptions: create(PromptCacheOptionsSchema, { type: CacheControlType.EPHEMERAL }),\n\t\tconfiguration: create(CompletionConfigurationSchema, {\n\t\t\tmaxTokens: BigInt(input.maxTokens ?? input.model.maxTokens ?? 0),\n\t\t\ttemperature: input.temperature ?? 0,\n\t\t\tstopPatterns: [...DEVIN_DEFAULT_STOP_PATTERNS],\n\t\t}),\n\t});\n}\n\nfunction toolDefinition(tool: Tool) {\n\treturn create(ChatToolDefinitionSchema, {\n\t\tname: tool.name,\n\t\tdescription: tool.description,\n\t\tjsonSchemaString: JSON.stringify(tool.parameters ?? {}),\n\t});\n}\n\nfunction mapHistory(messages: readonly Message[], cascadeId: string): ChatMessagePrompt[] {\n\tconst prompts: ChatMessagePrompt[] = [];\n\tfor (const [index, message] of messages.entries()) {\n\t\tconst id = `${cascadeId}\\u0000${index}\\u0000${message.role}`;\n\t\tif (message.role === \"user\") prompts.push(userPrompt(message.content, id));\n\t\telse if (message.role === \"assistant\") prompts.push(assistantPrompt(message, id));\n\t\telse if (message.role === \"toolResult\") prompts.push(toolResultPrompt(message, id));\n\t}\n\treturn prompts;\n}\n\nfunction userPrompt(content: Extract<Message, { role: \"user\" }>[\"content\"], messageId: string): ChatMessagePrompt {\n\tconst text = typeof content === \"string\" ? content : joinText(content);\n\treturn create(ChatMessagePromptSchema, {\n\t\tmessageId,\n\t\tsource: ChatMessageSource.USER,\n\t\tprompt: text,\n\t});\n}\n\nfunction assistantPrompt(message: Extract<Message, { role: \"assistant\" }>, messageId: string): ChatMessagePrompt {\n\tconst text: string[] = [];\n\tlet thinking = \"\";\n\tlet signature = \"\";\n\tconst toolCalls = [];\n\tfor (const block of message.content) {\n\t\tif (block.type === \"text\") text.push(block.text);\n\t\telse if (block.type === \"thinking\") {\n\t\t\tthinking += block.thinking;\n\t\t\tif (block.thinkingSignature) signature = block.thinkingSignature;\n\t\t} else if (block.type === \"toolCall\") {\n\t\t\ttoolCalls.push(\n\t\t\t\tcreate(ChatToolCallSchema, {\n\t\t\t\t\tid: block.id,\n\t\t\t\t\tname: block.name,\n\t\t\t\t\targumentsJson: JSON.stringify(block.arguments ?? {}),\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\treturn create(ChatMessagePromptSchema, {\n\t\tmessageId,\n\t\tsource: ChatMessageSource.SYSTEM,\n\t\tprompt: text.join(\"\\n\"),\n\t\tthinking,\n\t\tsignature,\n\t\ttoolCalls,\n\t});\n}\n\nfunction toolResultPrompt(message: Extract<Message, { role: \"toolResult\" }>, messageId: string): ChatMessagePrompt {\n\treturn create(ChatMessagePromptSchema, {\n\t\tmessageId,\n\t\tsource: ChatMessageSource.TOOL,\n\t\tprompt: joinText(message.content),\n\t\ttoolCallId: message.toolCallId,\n\t\ttoolResultIsError: message.isError === true,\n\t});\n}\n\nfunction joinText(content: readonly { type: string; text?: string }[]): string {\n\treturn content\n\t\t.filter((block) => block.type === \"text\" && typeof block.text === \"string\")\n\t\t.map((block) => block.text as string)\n\t\t.join(\"\\n\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"request.js","sourceRoot":"","sources":["../../../src/api/devin-agent/request.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Builds the Cascade `GetChatMessage` request from senpi's provider-neutral\n * context.\n *\n * Cascade has no system role: the system prompt travels in the top-level\n * `prompt` field, and history is a flat list of `ChatMessagePrompt` entries\n * whose `source` carries the role. Message ids must be UUID-shaped; they are\n * derived deterministically from the conversation id and the entry index so a\n * retried turn re-sends the same ids instead of forking the server-side\n * transcript, while a native Devin turn is replayed under the id the server\n * minted for it.\n */\n\nimport { create } from \"@bufbuild/protobuf\";\nimport type { Context, Message, Model, Tool } from \"../../types.ts\";\nimport { deterministicUuid } from \"../cursor-agent/deterministic-id.ts\";\nimport {\n\tCacheControlType,\n\ttype ChatMessagePrompt,\n\tChatMessagePromptSchema,\n\tChatMessageRequestType,\n\tChatMessageSource,\n\tChatToolCallSchema,\n\tChatToolDefinitionSchema,\n\tCompletionConfigurationSchema,\n\tConversationalPlannerMode,\n\ttype GetChatMessageRequest,\n\tGetChatMessageRequestSchema,\n\ttype ImageData,\n\tImageDataSchema,\n\tPromptCacheOptionsSchema,\n} from \"./gen/cascade_pb.ts\";\nimport { devinCliMetadata } from \"./metadata.ts\";\n\n/** Cascade's own stop vocabulary; the server echoes these as STOP_PATTERN. */\nexport const DEVIN_DEFAULT_STOP_PATTERNS = [\n\t\"<|user|>\",\n\t\"<|bot|>\",\n\t\"<|context_request|>\",\n\t\"<|endoftext|>\",\n\t\"<|end_of_turn|>\",\n] as const;\n\nconst DEFAULT_MAX_TOKENS = 64_000;\nconst DEFAULT_TEMPERATURE = 0.4;\n/** Cascade refuses a temperature of exactly 0 (proto3 drops it) with an opaque invalid_argument. */\nconst MIN_TEMPERATURE = 0.0001;\n\nexport interface DevinModelAssignment {\n\tmodelUid: string;\n\tassignmentJwt: string;\n}\n\nexport interface DevinChatRequestInput {\n\tmodel: Model<\"devin-agent\">;\n\tcontext: Context;\n\tapiKey: string | undefined;\n\tuserJwt?: string;\n\tcascadeId: string;\n\tassignment?: DevinModelAssignment;\n\tmaxTokens?: number;\n\ttemperature?: number;\n\ttopP?: number;\n\tstopSequences?: readonly string[];\n}\n\ntype UserMessage = Extract<Message, { role: \"user\" }>;\ntype AssistantMessage = Extract<Message, { role: \"assistant\" }>;\ntype ToolResultMessage = Extract<Message, { role: \"toolResult\" }>;\n\nexport function buildDevinChatRequest(input: DevinChatRequestInput): GetChatMessageRequest {\n\tconst temperature = Math.max(input.temperature ?? DEFAULT_TEMPERATURE, MIN_TEMPERATURE);\n\tconst stopPatterns = [...DEVIN_DEFAULT_STOP_PATTERNS, ...(input.stopSequences ?? [])];\n\treturn create(GetChatMessageRequestSchema, {\n\t\tmetadata: devinCliMetadata(input.apiKey, input.userJwt ?? \"\"),\n\t\tprompt: input.context.systemPrompt ?? \"\",\n\t\tchatMessagePrompts: mapHistory(input.context.messages, input.cascadeId, input.model),\n\t\trequestType: ChatMessageRequestType.CASCADE,\n\t\tplannerMode: ConversationalPlannerMode.DEFAULT,\n\t\tchatModelUid: input.assignment?.modelUid ?? input.model.upstreamModelId ?? input.model.id,\n\t\t...(input.assignment ? { modelAssignmentJwt: input.assignment.assignmentJwt } : {}),\n\t\tcascadeId: input.cascadeId,\n\t\texecutionId: crypto.randomUUID(),\n\t\ttools: (input.context.tools ?? []).map(toolDefinition),\n\t\ttoolChoice: { choice: { case: \"optionName\", value: \"auto\" } },\n\t\tsystemPromptCacheOptions: create(PromptCacheOptionsSchema, { type: CacheControlType.EPHEMERAL }),\n\t\tdisableParallelToolCalls: input.model.compat?.supportsParallelToolCalls !== true,\n\t\tconfiguration: create(CompletionConfigurationSchema, {\n\t\t\tnumCompletions: 1n,\n\t\t\tmaxTokens: BigInt(input.maxTokens ?? input.model.maxTokens ?? DEFAULT_MAX_TOKENS),\n\t\t\tmaxNewlines: 200n,\n\t\t\ttemperature,\n\t\t\tfirstTemperature: temperature,\n\t\t\ttopK: 50n,\n\t\t\ttopP: input.topP ?? 1,\n\t\t\tstopPatterns,\n\t\t\tfimEotProbThreshold: 1,\n\t\t}),\n\t});\n}\n\n/** The router scores the latest user turn alone; the chat request mints the turn's id. */\nexport function buildDevinRouterPrompt(messages: readonly Message[]): ChatMessagePrompt | undefined {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst message = messages[index];\n\t\tif (message?.role === \"user\") return userPrompt(message, \"\");\n\t}\n\treturn undefined;\n}\n\nfunction toolDefinition(tool: Tool) {\n\treturn create(ChatToolDefinitionSchema, {\n\t\tname: tool.name,\n\t\tdescription: tool.description,\n\t\tjsonSchemaString: JSON.stringify(tool.parameters ?? {}),\n\t\tstrict: false,\n\t});\n}\n\nfunction mapHistory(messages: readonly Message[], cascadeId: string, model: Model<\"devin-agent\">): ChatMessagePrompt[] {\n\tconst prompts: ChatMessagePrompt[] = [];\n\tfor (const [index, message] of messages.entries()) {\n\t\tconst seed = `${cascadeId}\\u0000${index}\\u0000${message.role}`;\n\t\tif (message.role === \"user\") prompts.push(userPrompt(message, deterministicUuid(seed)));\n\t\telse if (message.role === \"assistant\") {\n\t\t\tconst prompt = assistantPrompt(message, model, `bot-${deterministicUuid(seed)}`);\n\t\t\tif (prompt) prompts.push(prompt);\n\t\t} else if (message.role === \"toolResult\") {\n\t\t\tprompts.push(toolResultPrompt(message, deterministicUuid(`${seed}\\u0000${message.toolCallId}`)));\n\t\t}\n\t}\n\treturn prompts;\n}\n\nfunction userPrompt(message: UserMessage, messageId: string): ChatMessagePrompt {\n\tconst { text, images } = splitContent(typeof message.content === \"string\" ? [] : message.content);\n\treturn create(ChatMessagePromptSchema, {\n\t\tmessageId,\n\t\tsource: ChatMessageSource.USER,\n\t\tprompt: typeof message.content === \"string\" ? message.content : text,\n\t\timages,\n\t});\n}\n\nfunction assistantPrompt(\n\tmessage: AssistantMessage,\n\tmodel: Model<\"devin-agent\">,\n\tfallbackId: string,\n): ChatMessagePrompt | undefined {\n\tconst native = message.api === model.api && message.provider === model.provider && message.model === model.id;\n\tlet text = \"\";\n\tlet thinking = \"\";\n\tlet signature = \"\";\n\tconst toolCalls = [];\n\tfor (const block of message.content) {\n\t\tif (block.type === \"text\") text += block.text;\n\t\telse if (block.type === \"thinking\") {\n\t\t\tthinking += block.thinking;\n\t\t\tif (native && !signature && block.thinkingSignature) signature = block.thinkingSignature;\n\t\t} else if (block.type === \"toolCall\") {\n\t\t\ttoolCalls.push(\n\t\t\t\tcreate(ChatToolCallSchema, {\n\t\t\t\t\tid: block.id,\n\t\t\t\t\tname: block.name,\n\t\t\t\t\targumentsJson: JSON.stringify(block.arguments ?? {}),\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\tif (!text && !thinking && !signature && toolCalls.length === 0) return undefined;\n\treturn create(ChatMessagePromptSchema, {\n\t\tmessageId: native && message.responseId ? message.responseId : fallbackId,\n\t\tsource: ChatMessageSource.SYSTEM,\n\t\tprompt: text,\n\t\tthinking,\n\t\tsignature,\n\t\tsignatureType: \"\",\n\t\ttoolCalls,\n\t});\n}\n\nfunction toolResultPrompt(message: ToolResultMessage, messageId: string): ChatMessagePrompt {\n\tconst { text, images } = splitContent(message.content);\n\treturn create(ChatMessagePromptSchema, {\n\t\tmessageId,\n\t\tsource: ChatMessageSource.TOOL,\n\t\tprompt: text,\n\t\timages,\n\t\ttoolCallId: message.toolCallId,\n\t\ttoolResultIsError: message.isError === true,\n\t});\n}\n\nfunction splitContent(\n\tcontent: readonly ({ type: \"text\"; text: string } | { type: \"image\"; data: string; mimeType: string })[],\n): { text: string; images: ImageData[] } {\n\tlet text = \"\";\n\tconst images: ImageData[] = [];\n\tfor (const block of content) {\n\t\tif (block.type === \"text\") text += block.text;\n\t\telse images.push(create(ImageDataSchema, { base64Data: block.data, mimeType: block.mimeType }));\n\t}\n\treturn { text, images };\n}\n"]}
|
|
@@ -9,12 +9,18 @@
|
|
|
9
9
|
import type { AssistantMessage } from "../../types.ts";
|
|
10
10
|
import type { AssistantMessageEventStream } from "../../utils/event-stream.ts";
|
|
11
11
|
import { type GetChatMessageResponse } from "./gen/cascade_pb.ts";
|
|
12
|
+
export interface DevinToolCallState {
|
|
13
|
+
contentIndex: number;
|
|
14
|
+
/** Raw JSON accumulated across chunks; the content block holds the parsed view. */
|
|
15
|
+
argumentsJson: string;
|
|
16
|
+
}
|
|
12
17
|
export interface DevinStreamState {
|
|
13
18
|
textIndex: number | undefined;
|
|
14
19
|
thinkingIndex: number | undefined;
|
|
15
|
-
toolCalls: Map<string,
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
toolCalls: Map<string, DevinToolCallState>;
|
|
21
|
+
/** Chunks after the first arrive without an id; they belong to this call. */
|
|
22
|
+
activeToolCallId: string | undefined;
|
|
18
23
|
}
|
|
24
|
+
export declare function createDevinStreamState(): DevinStreamState;
|
|
19
25
|
export declare function applyDevinResponse(message: GetChatMessageResponse, output: AssistantMessage, events: AssistantMessageEventStream, state: DevinStreamState): void;
|
|
20
26
|
//# sourceMappingURL=stream-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-state.d.ts","sourceRoot":"","sources":["../../../src/api/devin-agent/stream-state.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAY,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"stream-state.d.ts","sourceRoot":"","sources":["../../../src/api/devin-agent/stream-state.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAY,MAAM,gBAAgB,CAAC;AACjE,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAE/E,OAAO,EAAE,KAAK,sBAAsB,EAAc,MAAM,qBAAqB,CAAC;AAE9E,MAAM,WAAW,kBAAkB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,mFAAmF;IACnF,aAAa,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAChC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC3C,6EAA6E;IAC7E,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AAED,wBAAgB,sBAAsB,IAAI,gBAAgB,CAEzD;AAED,wBAAgB,kBAAkB,CACjC,OAAO,EAAE,sBAAsB,EAC/B,MAAM,EAAE,gBAAgB,EACxB,MAAM,EAAE,2BAA2B,EACnC,KAAK,EAAE,gBAAgB,GACrB,IAAI,CASN"}
|
|
@@ -6,7 +6,11 @@
|
|
|
6
6
|
* or closes them. This module owns the open-block state so the adapter emits
|
|
7
7
|
* senpi's start/delta/end triples in the right order.
|
|
8
8
|
*/
|
|
9
|
+
import { parseStreamingJson } from "../../utils/json-parse.js";
|
|
9
10
|
import { StopReason } from "./gen/cascade_pb.js";
|
|
11
|
+
export function createDevinStreamState() {
|
|
12
|
+
return { textIndex: undefined, thinkingIndex: undefined, toolCalls: new Map(), activeToolCallId: undefined };
|
|
13
|
+
}
|
|
10
14
|
export function applyDevinResponse(message, output, events, state) {
|
|
11
15
|
if (message.messageId && !output.responseId)
|
|
12
16
|
output.responseId = message.messageId;
|
|
@@ -65,33 +69,34 @@ function appendToolCall(call, output, events, state) {
|
|
|
65
69
|
closeText(output, events, state);
|
|
66
70
|
if (state.thinkingIndex !== undefined)
|
|
67
71
|
closeThinking(output, events, state);
|
|
68
|
-
const
|
|
69
|
-
if (
|
|
70
|
-
const open = output.content[existing.contentIndex];
|
|
71
|
-
if (open?.type === "toolCall" && call.argumentsJson) {
|
|
72
|
-
open.arguments = parseArguments(call.argumentsJson, open.arguments);
|
|
73
|
-
events.push({
|
|
74
|
-
type: "toolcall_delta",
|
|
75
|
-
contentIndex: existing.contentIndex,
|
|
76
|
-
delta: call.argumentsJson,
|
|
77
|
-
partial: output,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
72
|
+
const toolCallId = call.id || state.activeToolCallId;
|
|
73
|
+
if (!toolCallId)
|
|
80
74
|
return;
|
|
75
|
+
state.activeToolCallId = toolCallId;
|
|
76
|
+
let entry = state.toolCalls.get(toolCallId);
|
|
77
|
+
if (entry === undefined) {
|
|
78
|
+
const block = { type: "toolCall", id: toolCallId, name: call.name, arguments: {} };
|
|
79
|
+
output.content.push(block);
|
|
80
|
+
entry = { contentIndex: output.content.length - 1, argumentsJson: "" };
|
|
81
|
+
state.toolCalls.set(toolCallId, entry);
|
|
82
|
+
events.push({ type: "toolcall_start", contentIndex: entry.contentIndex, partial: output });
|
|
81
83
|
}
|
|
82
|
-
const block =
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
84
|
+
const block = output.content[entry.contentIndex];
|
|
85
|
+
if (block?.type !== "toolCall")
|
|
86
|
+
return;
|
|
87
|
+
if (call.name)
|
|
88
|
+
block.name = call.name;
|
|
89
|
+
if (!call.argumentsJson)
|
|
90
|
+
return;
|
|
91
|
+
// A chunk either repeats everything so far plus new bytes, or carries only the new bytes.
|
|
92
|
+
const accumulated = call.argumentsJson.startsWith(entry.argumentsJson)
|
|
93
|
+
? call.argumentsJson
|
|
94
|
+
: entry.argumentsJson + call.argumentsJson;
|
|
95
|
+
const delta = accumulated.slice(entry.argumentsJson.length);
|
|
96
|
+
entry.argumentsJson = accumulated;
|
|
97
|
+
block.arguments = parseStreamingJson(accumulated);
|
|
98
|
+
if (delta)
|
|
99
|
+
events.push({ type: "toolcall_delta", contentIndex: entry.contentIndex, delta, partial: output });
|
|
95
100
|
}
|
|
96
101
|
function closeText(output, events, state) {
|
|
97
102
|
const index = state.textIndex;
|
|
@@ -137,17 +142,4 @@ function mapStopReason(reason) {
|
|
|
137
142
|
return "stop";
|
|
138
143
|
}
|
|
139
144
|
}
|
|
140
|
-
function parseArguments(json, fallback) {
|
|
141
|
-
if (!json)
|
|
142
|
-
return fallback;
|
|
143
|
-
try {
|
|
144
|
-
const parsed = JSON.parse(json);
|
|
145
|
-
return parsed !== null && typeof parsed === "object" && !Array.isArray(parsed)
|
|
146
|
-
? parsed
|
|
147
|
-
: fallback;
|
|
148
|
-
}
|
|
149
|
-
catch {
|
|
150
|
-
return fallback;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
145
|
//# sourceMappingURL=stream-state.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream-state.js","sourceRoot":"","sources":["../../../src/api/devin-agent/stream-state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Cascade delta bookkeeping.\n *\n * One Cascade response frame can carry a thinking delta, a text delta and a\n * finished tool call at once, and blocks are implicit: the server never opens\n * or closes them. This module owns the open-block state so the adapter emits\n * senpi's start/delta/end triples in the right order.\n */\n\nimport type { AssistantMessage, ToolCall } from \"../../types.ts\";\nimport type { AssistantMessageEventStream } from \"../../utils/event-stream.ts\";\nimport { type GetChatMessageResponse, StopReason } from \"./gen/cascade_pb.ts\";\n\nexport interface DevinStreamState {\n\ttextIndex: number | undefined;\n\tthinkingIndex: number | undefined;\n\ttoolCalls: Map<string, { contentIndex: number }>;\n}\n\nexport function applyDevinResponse(\n\tmessage: GetChatMessageResponse,\n\toutput: AssistantMessage,\n\tevents: AssistantMessageEventStream,\n\tstate: DevinStreamState,\n): void {\n\tif (message.messageId && !output.responseId) output.responseId = message.messageId;\n\tif (message.actualModelUid) output.responseModel = message.actualModelUid;\n\n\tif (message.deltaThinking) appendThinking(message, output, events, state);\n\tif (message.deltaText) appendText(message.deltaText, output, events, state);\n\tfor (const call of message.deltaToolCalls) appendToolCall(call, output, events, state);\n\tif (message.usage) applyUsage(message, output);\n\tif (message.stopReason !== StopReason.UNSPECIFIED) output.stopReason = mapStopReason(message.stopReason);\n}\n\nfunction appendThinking(\n\tmessage: GetChatMessageResponse,\n\toutput: AssistantMessage,\n\tevents: AssistantMessageEventStream,\n\tstate: DevinStreamState,\n): void {\n\t// A thinking block interleaved after text starts a new block, matching the\n\t// order Cascade streamed it in.\n\tif (state.textIndex !== undefined) closeText(output, events, state);\n\tif (state.thinkingIndex === undefined) {\n\t\toutput.content.push({ type: \"thinking\", thinking: \"\", ...(message.thinkingRedacted ? { redacted: true } : {}) });\n\t\tstate.thinkingIndex = output.content.length - 1;\n\t\tevents.push({ type: \"thinking_start\", contentIndex: state.thinkingIndex, partial: output });\n\t}\n\tconst block = output.content[state.thinkingIndex];\n\tif (block?.type !== \"thinking\") return;\n\tblock.thinking += message.deltaThinking;\n\tif (message.deltaSignature) block.thinkingSignature = message.deltaSignature;\n\tevents.push({\n\t\ttype: \"thinking_delta\",\n\t\tcontentIndex: state.thinkingIndex,\n\t\tdelta: message.deltaThinking,\n\t\tpartial: output,\n\t});\n}\n\nfunction appendText(\n\tdelta: string,\n\toutput: AssistantMessage,\n\tevents: AssistantMessageEventStream,\n\tstate: DevinStreamState,\n): void {\n\tif (state.thinkingIndex !== undefined) closeThinking(output, events, state);\n\tif (state.textIndex === undefined) {\n\t\toutput.content.push({ type: \"text\", text: \"\" });\n\t\tstate.textIndex = output.content.length - 1;\n\t\tevents.push({ type: \"text_start\", contentIndex: state.textIndex, partial: output });\n\t}\n\tconst block = output.content[state.textIndex];\n\tif (block?.type !== \"text\") return;\n\tblock.text += delta;\n\tevents.push({ type: \"text_delta\", contentIndex: state.textIndex, delta, partial: output });\n}\n\nfunction appendToolCall(\n\tcall: { id: string; name: string; argumentsJson: string },\n\toutput: AssistantMessage,\n\tevents: AssistantMessageEventStream,\n\tstate: DevinStreamState,\n): void {\n\tif (state.textIndex !== undefined) closeText(output, events, state);\n\tif (state.thinkingIndex !== undefined) closeThinking(output, events, state);\n\tconst existing = state.toolCalls.get(call.id);\n\tif (existing !== undefined) {\n\t\tconst open = output.content[existing.contentIndex];\n\t\tif (open?.type === \"toolCall\" && call.argumentsJson) {\n\t\t\topen.arguments = parseArguments(call.argumentsJson, open.arguments);\n\t\t\tevents.push({\n\t\t\t\ttype: \"toolcall_delta\",\n\t\t\t\tcontentIndex: existing.contentIndex,\n\t\t\t\tdelta: call.argumentsJson,\n\t\t\t\tpartial: output,\n\t\t\t});\n\t\t}\n\t\treturn;\n\t}\n\tconst block: ToolCall = {\n\t\ttype: \"toolCall\",\n\t\tid: call.id,\n\t\tname: call.name,\n\t\targuments: parseArguments(call.argumentsJson, {}),\n\t};\n\toutput.content.push(block);\n\tconst contentIndex = output.content.length - 1;\n\tstate.toolCalls.set(call.id, { contentIndex });\n\tevents.push({ type: \"toolcall_start\", contentIndex, partial: output });\n\tif (call.argumentsJson) {\n\t\tevents.push({ type: \"toolcall_delta\", contentIndex, delta: call.argumentsJson, partial: output });\n\t}\n}\n\nfunction closeText(output: AssistantMessage, events: AssistantMessageEventStream, state: DevinStreamState): void {\n\tconst index = state.textIndex;\n\tif (index === undefined) return;\n\tconst block = output.content[index];\n\tstate.textIndex = undefined;\n\tif (block?.type === \"text\")\n\t\tevents.push({ type: \"text_end\", contentIndex: index, content: block.text, partial: output });\n}\n\nfunction closeThinking(output: AssistantMessage, events: AssistantMessageEventStream, state: DevinStreamState): void {\n\tconst index = state.thinkingIndex;\n\tif (index === undefined) return;\n\tconst block = output.content[index];\n\tstate.thinkingIndex = undefined;\n\tif (block?.type === \"thinking\")\n\t\tevents.push({ type: \"thinking_end\", contentIndex: index, content: block.thinking, partial: output });\n}\n\nfunction applyUsage(message: GetChatMessageResponse, output: AssistantMessage): void {\n\tconst usage = message.usage;\n\tif (!usage) return;\n\toutput.usage.input = Number(usage.inputTokens);\n\toutput.usage.output = Number(usage.outputTokens);\n\toutput.usage.cacheRead = Number(usage.cacheReadTokens);\n\toutput.usage.cacheWrite = Number(usage.cacheWriteTokens);\n\toutput.usage.totalTokens =\n\t\toutput.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;\n}\n\n/** Cascade's stop vocabulary reduced to senpi's. */\nfunction mapStopReason(reason: StopReason): AssistantMessage[\"stopReason\"] {\n\tswitch (reason) {\n\t\tcase StopReason.FUNCTION_CALL:\n\t\t\treturn \"toolUse\";\n\t\tcase StopReason.MAX_TOKENS:\n\t\tcase StopReason.MAX_NEWLINES:\n\t\t\treturn \"length\";\n\t\tcase StopReason.ERROR:\n\t\tcase StopReason.CONTENT_FILTER:\n\t\t\treturn \"error\";\n\t\tdefault:\n\t\t\treturn \"stop\";\n\t}\n}\n\nfunction parseArguments(json: string, fallback: Record<string, unknown>): Record<string, unknown> {\n\tif (!json) return fallback;\n\ttry {\n\t\tconst parsed = JSON.parse(json) as unknown;\n\t\treturn parsed !== null && typeof parsed === \"object\" && !Array.isArray(parsed)\n\t\t\t? (parsed as Record<string, unknown>)\n\t\t\t: fallback;\n\t} catch {\n\t\treturn fallback;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"stream-state.js","sourceRoot":"","sources":["../../../src/api/devin-agent/stream-state.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Cascade delta bookkeeping.\n *\n * One Cascade response frame can carry a thinking delta, a text delta and a\n * finished tool call at once, and blocks are implicit: the server never opens\n * or closes them. This module owns the open-block state so the adapter emits\n * senpi's start/delta/end triples in the right order.\n */\n\nimport type { AssistantMessage, ToolCall } from \"../../types.ts\";\nimport type { AssistantMessageEventStream } from \"../../utils/event-stream.ts\";\nimport { parseStreamingJson } from \"../../utils/json-parse.ts\";\nimport { type GetChatMessageResponse, StopReason } from \"./gen/cascade_pb.ts\";\n\nexport interface DevinToolCallState {\n\tcontentIndex: number;\n\t/** Raw JSON accumulated across chunks; the content block holds the parsed view. */\n\targumentsJson: string;\n}\n\nexport interface DevinStreamState {\n\ttextIndex: number | undefined;\n\tthinkingIndex: number | undefined;\n\ttoolCalls: Map<string, DevinToolCallState>;\n\t/** Chunks after the first arrive without an id; they belong to this call. */\n\tactiveToolCallId: string | undefined;\n}\n\nexport function createDevinStreamState(): DevinStreamState {\n\treturn { textIndex: undefined, thinkingIndex: undefined, toolCalls: new Map(), activeToolCallId: undefined };\n}\n\nexport function applyDevinResponse(\n\tmessage: GetChatMessageResponse,\n\toutput: AssistantMessage,\n\tevents: AssistantMessageEventStream,\n\tstate: DevinStreamState,\n): void {\n\tif (message.messageId && !output.responseId) output.responseId = message.messageId;\n\tif (message.actualModelUid) output.responseModel = message.actualModelUid;\n\n\tif (message.deltaThinking) appendThinking(message, output, events, state);\n\tif (message.deltaText) appendText(message.deltaText, output, events, state);\n\tfor (const call of message.deltaToolCalls) appendToolCall(call, output, events, state);\n\tif (message.usage) applyUsage(message, output);\n\tif (message.stopReason !== StopReason.UNSPECIFIED) output.stopReason = mapStopReason(message.stopReason);\n}\n\nfunction appendThinking(\n\tmessage: GetChatMessageResponse,\n\toutput: AssistantMessage,\n\tevents: AssistantMessageEventStream,\n\tstate: DevinStreamState,\n): void {\n\t// A thinking block interleaved after text starts a new block, matching the\n\t// order Cascade streamed it in.\n\tif (state.textIndex !== undefined) closeText(output, events, state);\n\tif (state.thinkingIndex === undefined) {\n\t\toutput.content.push({ type: \"thinking\", thinking: \"\", ...(message.thinkingRedacted ? { redacted: true } : {}) });\n\t\tstate.thinkingIndex = output.content.length - 1;\n\t\tevents.push({ type: \"thinking_start\", contentIndex: state.thinkingIndex, partial: output });\n\t}\n\tconst block = output.content[state.thinkingIndex];\n\tif (block?.type !== \"thinking\") return;\n\tblock.thinking += message.deltaThinking;\n\tif (message.deltaSignature) block.thinkingSignature = message.deltaSignature;\n\tevents.push({\n\t\ttype: \"thinking_delta\",\n\t\tcontentIndex: state.thinkingIndex,\n\t\tdelta: message.deltaThinking,\n\t\tpartial: output,\n\t});\n}\n\nfunction appendText(\n\tdelta: string,\n\toutput: AssistantMessage,\n\tevents: AssistantMessageEventStream,\n\tstate: DevinStreamState,\n): void {\n\tif (state.thinkingIndex !== undefined) closeThinking(output, events, state);\n\tif (state.textIndex === undefined) {\n\t\toutput.content.push({ type: \"text\", text: \"\" });\n\t\tstate.textIndex = output.content.length - 1;\n\t\tevents.push({ type: \"text_start\", contentIndex: state.textIndex, partial: output });\n\t}\n\tconst block = output.content[state.textIndex];\n\tif (block?.type !== \"text\") return;\n\tblock.text += delta;\n\tevents.push({ type: \"text_delta\", contentIndex: state.textIndex, delta, partial: output });\n}\n\nfunction appendToolCall(\n\tcall: { id: string; name: string; argumentsJson: string },\n\toutput: AssistantMessage,\n\tevents: AssistantMessageEventStream,\n\tstate: DevinStreamState,\n): void {\n\tif (state.textIndex !== undefined) closeText(output, events, state);\n\tif (state.thinkingIndex !== undefined) closeThinking(output, events, state);\n\tconst toolCallId = call.id || state.activeToolCallId;\n\tif (!toolCallId) return;\n\tstate.activeToolCallId = toolCallId;\n\tlet entry = state.toolCalls.get(toolCallId);\n\tif (entry === undefined) {\n\t\tconst block: ToolCall = { type: \"toolCall\", id: toolCallId, name: call.name, arguments: {} };\n\t\toutput.content.push(block);\n\t\tentry = { contentIndex: output.content.length - 1, argumentsJson: \"\" };\n\t\tstate.toolCalls.set(toolCallId, entry);\n\t\tevents.push({ type: \"toolcall_start\", contentIndex: entry.contentIndex, partial: output });\n\t}\n\tconst block = output.content[entry.contentIndex];\n\tif (block?.type !== \"toolCall\") return;\n\tif (call.name) block.name = call.name;\n\tif (!call.argumentsJson) return;\n\t// A chunk either repeats everything so far plus new bytes, or carries only the new bytes.\n\tconst accumulated = call.argumentsJson.startsWith(entry.argumentsJson)\n\t\t? call.argumentsJson\n\t\t: entry.argumentsJson + call.argumentsJson;\n\tconst delta = accumulated.slice(entry.argumentsJson.length);\n\tentry.argumentsJson = accumulated;\n\tblock.arguments = parseStreamingJson(accumulated);\n\tif (delta) events.push({ type: \"toolcall_delta\", contentIndex: entry.contentIndex, delta, partial: output });\n}\n\nfunction closeText(output: AssistantMessage, events: AssistantMessageEventStream, state: DevinStreamState): void {\n\tconst index = state.textIndex;\n\tif (index === undefined) return;\n\tconst block = output.content[index];\n\tstate.textIndex = undefined;\n\tif (block?.type === \"text\")\n\t\tevents.push({ type: \"text_end\", contentIndex: index, content: block.text, partial: output });\n}\n\nfunction closeThinking(output: AssistantMessage, events: AssistantMessageEventStream, state: DevinStreamState): void {\n\tconst index = state.thinkingIndex;\n\tif (index === undefined) return;\n\tconst block = output.content[index];\n\tstate.thinkingIndex = undefined;\n\tif (block?.type === \"thinking\")\n\t\tevents.push({ type: \"thinking_end\", contentIndex: index, content: block.thinking, partial: output });\n}\n\nfunction applyUsage(message: GetChatMessageResponse, output: AssistantMessage): void {\n\tconst usage = message.usage;\n\tif (!usage) return;\n\toutput.usage.input = Number(usage.inputTokens);\n\toutput.usage.output = Number(usage.outputTokens);\n\toutput.usage.cacheRead = Number(usage.cacheReadTokens);\n\toutput.usage.cacheWrite = Number(usage.cacheWriteTokens);\n\toutput.usage.totalTokens =\n\t\toutput.usage.input + output.usage.output + output.usage.cacheRead + output.usage.cacheWrite;\n}\n\n/** Cascade's stop vocabulary reduced to senpi's. */\nfunction mapStopReason(reason: StopReason): AssistantMessage[\"stopReason\"] {\n\tswitch (reason) {\n\t\tcase StopReason.FUNCTION_CALL:\n\t\t\treturn \"toolUse\";\n\t\tcase StopReason.MAX_TOKENS:\n\t\tcase StopReason.MAX_NEWLINES:\n\t\t\treturn \"length\";\n\t\tcase StopReason.ERROR:\n\t\tcase StopReason.CONTENT_FILTER:\n\t\t\treturn \"error\";\n\t\tdefault:\n\t\t\treturn \"stop\";\n\t}\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connect end-of-stream trailer errors.
|
|
3
|
+
*
|
|
4
|
+
* Cascade rejects a turn (`invalid_argument`, `permission_denied`, ...) with an
|
|
5
|
+
* HTTP 200 whose only frame is the trailer `{ error: { code, message, details } }`.
|
|
6
|
+
* The trailer is the sole server-side evidence for such a rejection, so it is
|
|
7
|
+
* parsed with guards - never asserted - and its details are folded into the
|
|
8
|
+
* message a user sees.
|
|
9
|
+
*/
|
|
10
|
+
export interface DevinTrailerError {
|
|
11
|
+
code: string;
|
|
12
|
+
message: string;
|
|
13
|
+
formatted: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function readDevinTrailerError(trailer: string): DevinTrailerError | undefined;
|
|
16
|
+
//# sourceMappingURL=trailer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trailer.d.ts","sourceRoot":"","sources":["../../../src/api/devin-agent/trailer.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAmBpF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connect end-of-stream trailer errors.
|
|
3
|
+
*
|
|
4
|
+
* Cascade rejects a turn (`invalid_argument`, `permission_denied`, ...) with an
|
|
5
|
+
* HTTP 200 whose only frame is the trailer `{ error: { code, message, details } }`.
|
|
6
|
+
* The trailer is the sole server-side evidence for such a rejection, so it is
|
|
7
|
+
* parsed with guards - never asserted - and its details are folded into the
|
|
8
|
+
* message a user sees.
|
|
9
|
+
*/
|
|
10
|
+
const MAX_TRAILER_EVIDENCE_CHARS = 2000;
|
|
11
|
+
export function readDevinTrailerError(trailer) {
|
|
12
|
+
const text = trailer.trim();
|
|
13
|
+
if (!text)
|
|
14
|
+
return undefined;
|
|
15
|
+
let parsed;
|
|
16
|
+
try {
|
|
17
|
+
parsed = JSON.parse(text);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
if (!isRecord(parsed) || !isRecord(parsed.error))
|
|
23
|
+
return undefined;
|
|
24
|
+
const code = typeof parsed.error.code === "string" ? parsed.error.code : "";
|
|
25
|
+
const message = typeof parsed.error.message === "string" ? parsed.error.message : "";
|
|
26
|
+
if (!code && !message)
|
|
27
|
+
return undefined;
|
|
28
|
+
const detail = summarizeDetails(parsed.error.details);
|
|
29
|
+
return {
|
|
30
|
+
code,
|
|
31
|
+
message,
|
|
32
|
+
formatted: `Devin stream error${code ? ` ${code}` : ""}: ${message}${detail ? ` [details: ${detail}]` : ""}`,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function summarizeDetails(details) {
|
|
36
|
+
if (!Array.isArray(details) || details.length === 0)
|
|
37
|
+
return undefined;
|
|
38
|
+
const parts = [];
|
|
39
|
+
for (const entry of details) {
|
|
40
|
+
if (!isRecord(entry))
|
|
41
|
+
continue;
|
|
42
|
+
const type = typeof entry.type === "string" && entry.type ? entry.type : undefined;
|
|
43
|
+
const evidence = evidenceOf(entry);
|
|
44
|
+
const part = type && evidence ? `${type}: ${evidence}` : (type ?? evidence);
|
|
45
|
+
if (part)
|
|
46
|
+
parts.push(part);
|
|
47
|
+
}
|
|
48
|
+
const summary = parts.join("; ");
|
|
49
|
+
if (!summary)
|
|
50
|
+
return undefined;
|
|
51
|
+
return summary.length > MAX_TRAILER_EVIDENCE_CHARS ? `${summary.slice(0, MAX_TRAILER_EVIDENCE_CHARS)}…` : summary;
|
|
52
|
+
}
|
|
53
|
+
function evidenceOf(entry) {
|
|
54
|
+
if (entry.debug !== undefined) {
|
|
55
|
+
if (typeof entry.debug === "string")
|
|
56
|
+
return entry.debug;
|
|
57
|
+
try {
|
|
58
|
+
return JSON.stringify(entry.debug);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return typeof entry.value === "string" && entry.value ? entry.value : undefined;
|
|
65
|
+
}
|
|
66
|
+
function isRecord(value) {
|
|
67
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=trailer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trailer.js","sourceRoot":"","sources":["../../../src/api/devin-agent/trailer.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Connect end-of-stream trailer errors.\n *\n * Cascade rejects a turn (`invalid_argument`, `permission_denied`, ...) with an\n * HTTP 200 whose only frame is the trailer `{ error: { code, message, details } }`.\n * The trailer is the sole server-side evidence for such a rejection, so it is\n * parsed with guards - never asserted - and its details are folded into the\n * message a user sees.\n */\n\nconst MAX_TRAILER_EVIDENCE_CHARS = 2000;\n\nexport interface DevinTrailerError {\n\tcode: string;\n\tmessage: string;\n\tformatted: string;\n}\n\nexport function readDevinTrailerError(trailer: string): DevinTrailerError | undefined {\n\tconst text = trailer.trim();\n\tif (!text) return undefined;\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(text);\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (!isRecord(parsed) || !isRecord(parsed.error)) return undefined;\n\tconst code = typeof parsed.error.code === \"string\" ? parsed.error.code : \"\";\n\tconst message = typeof parsed.error.message === \"string\" ? parsed.error.message : \"\";\n\tif (!code && !message) return undefined;\n\tconst detail = summarizeDetails(parsed.error.details);\n\treturn {\n\t\tcode,\n\t\tmessage,\n\t\tformatted: `Devin stream error${code ? ` ${code}` : \"\"}: ${message}${detail ? ` [details: ${detail}]` : \"\"}`,\n\t};\n}\n\nfunction summarizeDetails(details: unknown): string | undefined {\n\tif (!Array.isArray(details) || details.length === 0) return undefined;\n\tconst parts: string[] = [];\n\tfor (const entry of details) {\n\t\tif (!isRecord(entry)) continue;\n\t\tconst type = typeof entry.type === \"string\" && entry.type ? entry.type : undefined;\n\t\tconst evidence = evidenceOf(entry);\n\t\tconst part = type && evidence ? `${type}: ${evidence}` : (type ?? evidence);\n\t\tif (part) parts.push(part);\n\t}\n\tconst summary = parts.join(\"; \");\n\tif (!summary) return undefined;\n\treturn summary.length > MAX_TRAILER_EVIDENCE_CHARS ? `${summary.slice(0, MAX_TRAILER_EVIDENCE_CHARS)}…` : summary;\n}\n\nfunction evidenceOf(entry: Record<string, unknown>): string | undefined {\n\tif (entry.debug !== undefined) {\n\t\tif (typeof entry.debug === \"string\") return entry.debug;\n\t\ttry {\n\t\t\treturn JSON.stringify(entry.debug);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn typeof entry.value === \"string\" && entry.value ? entry.value : undefined;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"]}
|