@factory/droid-sdk 0.7.0 → 0.8.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/dist/{chunk-C3KHERVH.js → chunk-4G2RKM2H.js} +4976 -3628
- package/dist/chunk-4G2RKM2H.js.map +1 -0
- package/dist/{chunk-5UXINOXG.mjs → chunk-ROFAQUG4.mjs} +7574 -6226
- package/dist/chunk-ROFAQUG4.mjs.map +1 -0
- package/dist/{index-D_SzTnFR.d.mts → index-_nUPGHpH.d.mts} +16625 -5933
- package/dist/{index-D_SzTnFR.d.ts → index-_nUPGHpH.d.ts} +16625 -5933
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9 -1
- package/dist/node.d.mts +24 -3
- package/dist/node.d.ts +24 -3
- package/dist/node.js +504 -374
- package/dist/node.js.map +1 -1
- package/dist/node.mjs +153 -23
- package/dist/node.mjs.map +1 -1
- package/docs/typescript-sdk-reference.md +903 -726
- package/examples/browser/daemon-model-discovery.ts +47 -0
- package/examples/browser/index.html +2 -1
- package/examples/browser/list-sessions.ts +1 -3
- package/examples/node/abort-session-stream.ts +2 -0
- package/examples/node/ask-user-elicitation.ts +11 -7
- package/examples/node/compact-session.ts +33 -18
- package/examples/node/custom-system-prompt.ts +35 -0
- package/examples/node/document-input.ts +58 -0
- package/examples/node/enter-spec-mode.ts +50 -29
- package/examples/node/external-mcp.ts +45 -0
- package/examples/node/fork-session.ts +21 -10
- package/examples/node/hook-execution.ts +37 -37
- package/examples/node/image-attachment.ts +8 -2
- package/examples/node/interrupt-session.ts +27 -8
- package/examples/node/model-discovery.ts +28 -0
- package/examples/node/model-selection.ts +35 -0
- package/examples/node/multi-turn-session.ts +4 -0
- package/examples/node/observability.ts +4 -17
- package/examples/node/partial-stream.ts +56 -0
- package/examples/node/permission-handler.ts +9 -4
- package/examples/node/rename-session.ts +7 -3
- package/examples/node/result-metadata.ts +10 -1
- package/examples/node/resume-session.ts +41 -0
- package/examples/node/rewind-session.ts +19 -9
- package/examples/node/run.ts +14 -7
- package/examples/node/sdk-mcp-tool.ts +10 -8
- package/examples/node/session-settings.ts +9 -9
- package/examples/node/session-stream.ts +17 -2
- package/examples/node/skills.ts +24 -0
- package/examples/node/spec-mode-new-session.ts +38 -10
- package/examples/node/spec-mode-same-session.ts +37 -3
- package/examples/node/structured-output.ts +30 -7
- package/package.json +1 -1
- package/dist/chunk-5UXINOXG.mjs.map +0 -1
- package/dist/chunk-C3KHERVH.js.map +0 -1
|
@@ -21,10 +21,13 @@ import { tmpdir } from 'node:os';
|
|
|
21
21
|
import { join } from 'node:path';
|
|
22
22
|
|
|
23
23
|
import {
|
|
24
|
+
type ClientPermissionHandler,
|
|
24
25
|
DroidInteractionMode,
|
|
26
|
+
DroidMessageType,
|
|
25
27
|
ReasoningEffort,
|
|
26
28
|
SessionNotificationSchema,
|
|
27
29
|
ToolConfirmationOutcome,
|
|
30
|
+
ToolConfirmationType,
|
|
28
31
|
createSession,
|
|
29
32
|
} from '@factory/droid-sdk/node';
|
|
30
33
|
|
|
@@ -33,11 +36,38 @@ const outputPath = join(tempDir, 'hello.txt');
|
|
|
33
36
|
|
|
34
37
|
let handoffSessionId: string | null = null;
|
|
35
38
|
|
|
39
|
+
const handlePermissionRequest: ClientPermissionHandler = ({
|
|
40
|
+
toolUses,
|
|
41
|
+
options,
|
|
42
|
+
}) => {
|
|
43
|
+
const exitsSpecMode =
|
|
44
|
+
toolUses.length > 0 &&
|
|
45
|
+
toolUses.every(
|
|
46
|
+
(toolUse) => toolUse.details.type === ToolConfirmationType.ExitSpecMode
|
|
47
|
+
);
|
|
48
|
+
const createsExpectedFile =
|
|
49
|
+
toolUses.length > 0 &&
|
|
50
|
+
toolUses.every(
|
|
51
|
+
(toolUse) =>
|
|
52
|
+
toolUse.details.type === ToolConfirmationType.Create &&
|
|
53
|
+
toolUse.details.filePath === outputPath
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const outcome =
|
|
57
|
+
exitsSpecMode || createsExpectedFile
|
|
58
|
+
? ToolConfirmationOutcome.ProceedOnce
|
|
59
|
+
: ToolConfirmationOutcome.Cancel;
|
|
60
|
+
if (!options.some((option) => option.value === outcome)) {
|
|
61
|
+
throw new Error(`Outcome not offered: ${outcome}`);
|
|
62
|
+
}
|
|
63
|
+
return outcome;
|
|
64
|
+
};
|
|
65
|
+
|
|
36
66
|
try {
|
|
37
67
|
const session = await createSession({
|
|
38
68
|
interactionMode: DroidInteractionMode.Spec,
|
|
39
69
|
specModeReasoningEffort: ReasoningEffort.High,
|
|
40
|
-
permissionHandler:
|
|
70
|
+
permissionHandler: handlePermissionRequest,
|
|
41
71
|
});
|
|
42
72
|
|
|
43
73
|
// The typed message stream carries no per-message session id, and the
|
|
@@ -54,10 +84,14 @@ try {
|
|
|
54
84
|
});
|
|
55
85
|
|
|
56
86
|
try {
|
|
57
|
-
for await (const
|
|
87
|
+
for await (const message of session.stream(
|
|
58
88
|
`Plan then create ${outputPath} containing "Hello from Droid".`
|
|
59
89
|
)) {
|
|
60
|
-
|
|
90
|
+
if (message.type === DroidMessageType.Result && !message.success) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
message.error?.message ?? `Turn ended: ${message.subtype}`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
61
95
|
}
|
|
62
96
|
} finally {
|
|
63
97
|
unsubscribe();
|
|
@@ -19,6 +19,31 @@ interface CodeReview {
|
|
|
19
19
|
}>;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
function isCodeReview(value: unknown): value is CodeReview {
|
|
23
|
+
if (
|
|
24
|
+
value === null ||
|
|
25
|
+
typeof value !== 'object' ||
|
|
26
|
+
!('summary' in value) ||
|
|
27
|
+
typeof value.summary !== 'string' ||
|
|
28
|
+
!('findings' in value) ||
|
|
29
|
+
!Array.isArray(value.findings)
|
|
30
|
+
) {
|
|
31
|
+
return false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return value.findings.every(
|
|
35
|
+
(finding) =>
|
|
36
|
+
finding !== null &&
|
|
37
|
+
typeof finding === 'object' &&
|
|
38
|
+
'line' in finding &&
|
|
39
|
+
typeof finding.line === 'number' &&
|
|
40
|
+
'severity' in finding &&
|
|
41
|
+
['low', 'medium', 'high'].includes(String(finding.severity)) &&
|
|
42
|
+
'message' in finding &&
|
|
43
|
+
typeof finding.message === 'string'
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
22
47
|
const result = await run(
|
|
23
48
|
`Review this code for correctness issues:
|
|
24
49
|
|
|
@@ -49,6 +74,7 @@ function getDisplayName(user) {
|
|
|
49
74
|
},
|
|
50
75
|
},
|
|
51
76
|
required: ['summary', 'findings'],
|
|
77
|
+
additionalProperties: false,
|
|
52
78
|
},
|
|
53
79
|
},
|
|
54
80
|
}
|
|
@@ -62,12 +88,9 @@ if (!result.success) {
|
|
|
62
88
|
throw new Error(`run() failed (${result.subtype}): ${detail}`);
|
|
63
89
|
}
|
|
64
90
|
|
|
65
|
-
//
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
throw new Error('run() succeeded but returned no structured output.');
|
|
91
|
+
// The SDK returns `unknown`; validate it before reading fields.
|
|
92
|
+
if (!isCodeReview(result.structuredOutput)) {
|
|
93
|
+
throw new Error('run() returned an unexpected structured output shape.');
|
|
69
94
|
}
|
|
70
95
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
console.log(JSON.stringify(review, null, 2));
|
|
96
|
+
console.log(JSON.stringify(result.structuredOutput, null, 2));
|