@factory/droid-sdk 0.6.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/README.md +35 -482
- package/dist/chunk-4G2RKM2H.js +25831 -0
- package/dist/chunk-4G2RKM2H.js.map +1 -0
- package/dist/chunk-ROFAQUG4.mjs +25831 -0
- package/dist/chunk-ROFAQUG4.mjs.map +1 -0
- package/dist/{index-CwXX5IUH.d.cts → index-_nUPGHpH.d.mts} +92630 -79659
- package/dist/{index-CwXX5IUH.d.ts → index-_nUPGHpH.d.ts} +92630 -79659
- package/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -93103
- package/dist/index.js +829 -11745
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +830 -0
- package/dist/index.mjs.map +1 -0
- package/dist/node.d.mts +757 -0
- package/dist/node.d.ts +757 -0
- package/dist/node.js +4731 -0
- package/dist/node.js.map +1 -0
- package/dist/node.mjs +4731 -0
- package/dist/node.mjs.map +1 -0
- package/docs/typescript-sdk-reference.md +1437 -0
- package/examples/browser/daemon-lifecycle.ts +95 -0
- package/examples/browser/daemon-model-discovery.ts +47 -0
- package/examples/browser/daemon-multi-session.ts +66 -0
- package/examples/browser/daemon-session.ts +73 -0
- package/examples/browser/index.html +69 -0
- package/examples/browser/list-sessions.ts +50 -0
- package/examples/node/abort-session-stream.ts +34 -0
- package/examples/node/ask-user-elicitation.ts +39 -0
- package/examples/node/compact-session.ts +63 -0
- package/examples/node/custom-system-prompt.ts +35 -0
- package/examples/node/document-input.ts +58 -0
- package/examples/node/enter-spec-mode.ts +87 -0
- package/examples/node/external-mcp.ts +45 -0
- package/examples/node/fork-session.ts +56 -0
- package/examples/node/hook-execution.ts +94 -0
- package/examples/node/image-attachment.ts +41 -0
- package/examples/node/init-metadata.ts +24 -0
- package/examples/node/interrupt-session.ts +55 -0
- package/examples/node/list-sessions.ts +20 -0
- package/examples/node/model-discovery.ts +28 -0
- package/examples/node/model-selection.ts +35 -0
- package/examples/node/multi-turn-session.ts +37 -0
- package/examples/node/observability.ts +75 -0
- package/examples/node/partial-stream.ts +56 -0
- package/examples/node/permission-handler.ts +60 -0
- package/examples/node/rename-session.ts +33 -0
- package/examples/node/result-metadata.ts +43 -0
- package/examples/node/resume-session.ts +41 -0
- package/examples/node/rewind-session.ts +79 -0
- package/examples/node/run.ts +32 -0
- package/examples/node/sdk-mcp-tool.ts +56 -0
- package/examples/node/session-settings.ts +35 -0
- package/examples/node/session-stream.ts +59 -0
- package/examples/node/skills.ts +24 -0
- package/examples/node/spec-mode-new-session.ts +120 -0
- package/examples/node/spec-mode-same-session.ts +119 -0
- package/examples/node/structured-output.ts +96 -0
- package/examples/node/tool-controls.ts +26 -0
- package/examples/package.json +3 -0
- package/package.json +20 -42
- package/dist/index.cjs +0 -12135
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -93103
- package/dist/protocol/index.cjs +0 -6466
- package/dist/protocol/index.cjs.map +0 -1
- package/dist/protocol/index.d.cts +0 -2
- package/dist/protocol/index.d.ts +0 -2
- package/dist/protocol/index.js +0 -6078
- package/dist/protocol/index.js.map +0 -1
- package/docs/daemon-usage-guide.md +0 -544
- package/docs/sdk-usage-guide.md +0 -748
- package/examples/abort-session-stream.ts +0 -34
- package/examples/daemon-multi-session.ts +0 -67
- package/examples/droid-dev-structured-output.ts +0 -44
- package/examples/fork-session.ts +0 -68
- package/examples/hook-execution.ts +0 -68
- package/examples/init-metadata.ts +0 -24
- package/examples/interrupt-session.ts +0 -35
- package/examples/list-sessions.ts +0 -19
- package/examples/multi-turn-session.ts +0 -40
- package/examples/permission-handler.ts +0 -41
- package/examples/readme-structured-output.ts +0 -26
- package/examples/result-metadata.ts +0 -63
- package/examples/run.ts +0 -39
- package/examples/sdk-mcp-tool.ts +0 -44
- package/examples/session-stream.ts +0 -57
- package/examples/spec-mode-new-session.ts +0 -61
- package/examples/spec-mode-same-session.ts +0 -72
- package/examples/structured-output.ts +0 -60
- package/examples/test-compact.ts +0 -65
- package/examples/test-rewind.ts +0 -87
- package/examples/tool-controls.ts +0 -37
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Spec mode: approve and hand off implementation to a new session.
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* npx tsx examples/spec-mode-new-session.ts
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
9
|
-
import { tmpdir } from 'node:os';
|
|
10
|
-
import { join } from 'node:path';
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
DroidInteractionMode,
|
|
14
|
-
ReasoningEffort,
|
|
15
|
-
ToolConfirmationOutcome,
|
|
16
|
-
ToolConfirmationType,
|
|
17
|
-
createSession,
|
|
18
|
-
} from '@factory/droid-sdk';
|
|
19
|
-
|
|
20
|
-
const tempDir = await mkdtemp(join(tmpdir(), 'droid-sdk-spec-'));
|
|
21
|
-
const outputPath = join(tempDir, 'hello.txt');
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
const session = await createSession({
|
|
25
|
-
apiKey: process.env.FACTORY_API_KEY!,
|
|
26
|
-
cwd: process.cwd(),
|
|
27
|
-
interactionMode: DroidInteractionMode.Spec,
|
|
28
|
-
specModeReasoningEffort: ReasoningEffort.High,
|
|
29
|
-
permissionHandler(params) {
|
|
30
|
-
const canExitSpec = params.toolUses.some(
|
|
31
|
-
(item) => item.details.type === ToolConfirmationType.ExitSpecMode
|
|
32
|
-
);
|
|
33
|
-
const onlyCreatesFile = params.toolUses.every(
|
|
34
|
-
(item) =>
|
|
35
|
-
item.details.type === ToolConfirmationType.Create &&
|
|
36
|
-
item.details.filePath === outputPath
|
|
37
|
-
);
|
|
38
|
-
|
|
39
|
-
if (canExitSpec) {
|
|
40
|
-
return ToolConfirmationOutcome.ProceedNewSessionHigh;
|
|
41
|
-
}
|
|
42
|
-
return onlyCreatesFile
|
|
43
|
-
? ToolConfirmationOutcome.ProceedOnce
|
|
44
|
-
: ToolConfirmationOutcome.Cancel;
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
try {
|
|
49
|
-
for await (const _msg of session.stream(
|
|
50
|
-
`Plan then create ${outputPath} containing "Hello from Droid".`
|
|
51
|
-
)) {
|
|
52
|
-
// Consume the stream until the handoff implementation finishes.
|
|
53
|
-
}
|
|
54
|
-
} finally {
|
|
55
|
-
await session.close();
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
console.log(await readFile(outputPath, 'utf8'));
|
|
59
|
-
} finally {
|
|
60
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
61
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Spec mode: approve and implement in the same session.
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* npx tsx examples/spec-mode-same-session.ts
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
9
|
-
import { tmpdir } from 'node:os';
|
|
10
|
-
import { join } from 'node:path';
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
DroidInteractionMode,
|
|
14
|
-
ReasoningEffort,
|
|
15
|
-
ToolConfirmationOutcome,
|
|
16
|
-
ToolConfirmationType,
|
|
17
|
-
createSession,
|
|
18
|
-
} from '@factory/droid-sdk';
|
|
19
|
-
|
|
20
|
-
const tempDir = await mkdtemp(join(tmpdir(), 'droid-sdk-spec-'));
|
|
21
|
-
const outputPath = join(tempDir, 'hello.txt');
|
|
22
|
-
|
|
23
|
-
try {
|
|
24
|
-
const session = await createSession({
|
|
25
|
-
apiKey: process.env.FACTORY_API_KEY!,
|
|
26
|
-
cwd: process.cwd(),
|
|
27
|
-
interactionMode: DroidInteractionMode.Spec,
|
|
28
|
-
specModeReasoningEffort: ReasoningEffort.High,
|
|
29
|
-
permissionHandler(params) {
|
|
30
|
-
const canExitSpec = params.toolUses.some(
|
|
31
|
-
(item) => item.details.type === ToolConfirmationType.ExitSpecMode
|
|
32
|
-
);
|
|
33
|
-
const onlyCreatesFile = params.toolUses.every(
|
|
34
|
-
(item) =>
|
|
35
|
-
item.details.type === ToolConfirmationType.Create &&
|
|
36
|
-
item.details.filePath === outputPath
|
|
37
|
-
);
|
|
38
|
-
const onlyEditsTempFile = params.toolUses.every(
|
|
39
|
-
(item) =>
|
|
40
|
-
item.details.type === ToolConfirmationType.ApplyPatch &&
|
|
41
|
-
item.details.filePath === outputPath
|
|
42
|
-
);
|
|
43
|
-
const onlyRunsTempCommand = params.toolUses.every(
|
|
44
|
-
(item) =>
|
|
45
|
-
item.details.type === ToolConfirmationType.Execute &&
|
|
46
|
-
item.details.fullCommand.includes(outputPath) &&
|
|
47
|
-
item.details.fullCommand.includes(tempDir)
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
return canExitSpec ||
|
|
51
|
-
onlyCreatesFile ||
|
|
52
|
-
onlyEditsTempFile ||
|
|
53
|
-
onlyRunsTempCommand
|
|
54
|
-
? ToolConfirmationOutcome.ProceedOnce
|
|
55
|
-
: ToolConfirmationOutcome.Cancel;
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
try {
|
|
60
|
-
for await (const _msg of session.stream(
|
|
61
|
-
`Plan then create ${outputPath} containing "Hello from Droid".`
|
|
62
|
-
)) {
|
|
63
|
-
// Consume the stream until implementation finishes.
|
|
64
|
-
}
|
|
65
|
-
} finally {
|
|
66
|
-
await session.close();
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
console.log(await readFile(outputPath, 'utf8'));
|
|
70
|
-
} finally {
|
|
71
|
-
await rm(tempDir, { recursive: true, force: true });
|
|
72
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Structured output example.
|
|
3
|
-
*
|
|
4
|
-
* Runs a prompt with the actual Droid CLI and requests a JSON object
|
|
5
|
-
* matching the provided schema.
|
|
6
|
-
*
|
|
7
|
-
* Usage:
|
|
8
|
-
* npx tsx examples/structured-output.ts
|
|
9
|
-
* npx tsx examples/structured-output.ts "Pick a favorite number between 1 and 42"
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import assert from 'node:assert/strict';
|
|
13
|
-
|
|
14
|
-
import { OutputFormatType, run } from '@factory/droid-sdk';
|
|
15
|
-
|
|
16
|
-
type FavoriteNumber = { favoriteNumber: number };
|
|
17
|
-
|
|
18
|
-
async function main(): Promise<void> {
|
|
19
|
-
const prompt =
|
|
20
|
-
process.argv.slice(2).join(' ') ||
|
|
21
|
-
'Pick a favorite number between 1 and 42.';
|
|
22
|
-
|
|
23
|
-
const outputFormat = {
|
|
24
|
-
type: OutputFormatType.JsonSchema,
|
|
25
|
-
schema: {
|
|
26
|
-
type: 'object',
|
|
27
|
-
properties: {
|
|
28
|
-
favoriteNumber: {
|
|
29
|
-
type: 'number',
|
|
30
|
-
minimum: 1,
|
|
31
|
-
maximum: 42,
|
|
32
|
-
},
|
|
33
|
-
},
|
|
34
|
-
required: ['favoriteNumber'],
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
console.log(`Sending prompt: "${prompt}"\n`);
|
|
39
|
-
|
|
40
|
-
const result = await run(prompt, {
|
|
41
|
-
apiKey: process.env.FACTORY_API_KEY!,
|
|
42
|
-
cwd: process.cwd(),
|
|
43
|
-
outputFormat,
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
const structuredOutput = result.structuredOutput as FavoriteNumber | null;
|
|
47
|
-
|
|
48
|
-
assert.ok(structuredOutput, 'Expected structuredOutput to be set');
|
|
49
|
-
assert.equal(typeof structuredOutput.favoriteNumber, 'number');
|
|
50
|
-
|
|
51
|
-
console.log('=== Structured output ===');
|
|
52
|
-
console.log(JSON.stringify(structuredOutput, null, 2));
|
|
53
|
-
|
|
54
|
-
console.log('\nStructured output example passed');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
main().catch((error: unknown) => {
|
|
58
|
-
console.error('Structured output example failed:', error);
|
|
59
|
-
process.exit(1);
|
|
60
|
-
});
|
package/examples/test-compact.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compact session example.
|
|
3
|
-
*
|
|
4
|
-
* Demonstrates `session.compactSession()` to summarize and compact
|
|
5
|
-
* session history. Creates a session, sends several messages to build
|
|
6
|
-
* up conversation history, then compacts and verifies newSessionId
|
|
7
|
-
* and removedCount.
|
|
8
|
-
*
|
|
9
|
-
* Usage:
|
|
10
|
-
* npx tsx examples/test-compact.ts
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
import { createSession, DroidMessageType } from '@factory/droid-sdk';
|
|
14
|
-
|
|
15
|
-
async function main(): Promise<void> {
|
|
16
|
-
const session = await createSession({
|
|
17
|
-
apiKey: process.env.FACTORY_API_KEY!,
|
|
18
|
-
cwd: process.cwd(),
|
|
19
|
-
});
|
|
20
|
-
try {
|
|
21
|
-
console.log(`Session created: ${session.sessionId}\n`);
|
|
22
|
-
|
|
23
|
-
const prompts = [
|
|
24
|
-
'Say "one" and nothing else',
|
|
25
|
-
'Say "two" and nothing else',
|
|
26
|
-
'Say "three" and nothing else',
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
for (let i = 0; i < prompts.length; i++) {
|
|
30
|
-
console.log(`=== Turn ${i + 1} ===`);
|
|
31
|
-
console.log(`Prompt: "${prompts[i]}"\n`);
|
|
32
|
-
|
|
33
|
-
for await (const msg of session.stream(prompts[i], {
|
|
34
|
-
includePartialMessages: true,
|
|
35
|
-
})) {
|
|
36
|
-
if (msg.type === DroidMessageType.AssistantTextDelta) {
|
|
37
|
-
process.stdout.write(msg.text);
|
|
38
|
-
}
|
|
39
|
-
if (msg.type === DroidMessageType.Result) {
|
|
40
|
-
console.log('\n');
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
console.log('=== Compacting session ===');
|
|
46
|
-
const compactResult = await session.compactSession({});
|
|
47
|
-
console.log(`Original session: ${session.sessionId}`);
|
|
48
|
-
console.log(`New session: ${compactResult.newSessionId}`);
|
|
49
|
-
console.log(`Removed messages: ${compactResult.removedCount}`);
|
|
50
|
-
|
|
51
|
-
if (compactResult.newSessionId && compactResult.removedCount > 0) {
|
|
52
|
-
console.log('\nCompaction succeeded.');
|
|
53
|
-
} else {
|
|
54
|
-
console.log('\nCompaction returned unexpected results.');
|
|
55
|
-
}
|
|
56
|
-
} finally {
|
|
57
|
-
await session.close();
|
|
58
|
-
console.log('Session closed.');
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
main().catch((err: unknown) => {
|
|
63
|
-
console.error('Error:', err);
|
|
64
|
-
process.exit(1);
|
|
65
|
-
});
|
package/examples/test-rewind.ts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Low-level rewind API example.
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* npx tsx examples/test-rewind.ts
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { randomUUID } from 'node:crypto';
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
AutonomyLevel,
|
|
12
|
-
DroidClient,
|
|
13
|
-
DroidWorkingState,
|
|
14
|
-
ProcessTransport,
|
|
15
|
-
SessionNotificationType,
|
|
16
|
-
} from '@factory/droid-sdk';
|
|
17
|
-
|
|
18
|
-
function waitForTurn(client: DroidClient): Promise<void> {
|
|
19
|
-
return new Promise((resolve) => {
|
|
20
|
-
let started = false;
|
|
21
|
-
const unsubscribe = client.onNotification((notification) => {
|
|
22
|
-
const params = notification['params'];
|
|
23
|
-
if (typeof params !== 'object' || params === null) {
|
|
24
|
-
return;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const event = (params as Record<string, unknown>)['notification'];
|
|
28
|
-
if (typeof event !== 'object' || event === null) {
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (
|
|
33
|
-
(event as Record<string, unknown>)['type'] !==
|
|
34
|
-
SessionNotificationType.DROID_WORKING_STATE_CHANGED
|
|
35
|
-
) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const newState = (event as Record<string, unknown>)['newState'];
|
|
40
|
-
started ||= newState !== DroidWorkingState.Idle;
|
|
41
|
-
if (started && newState === DroidWorkingState.Idle) {
|
|
42
|
-
unsubscribe();
|
|
43
|
-
resolve();
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
const transport = new ProcessTransport({ cwd: process.cwd() });
|
|
50
|
-
await transport.connect();
|
|
51
|
-
|
|
52
|
-
const client = new DroidClient({ transport });
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
await client.initializeSession({
|
|
56
|
-
machineId: 'default',
|
|
57
|
-
cwd: process.cwd(),
|
|
58
|
-
autonomyLevel: AutonomyLevel.High,
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
const messageId = randomUUID();
|
|
62
|
-
const done = waitForTurn(client);
|
|
63
|
-
await client.addUserMessage({
|
|
64
|
-
messageId,
|
|
65
|
-
text: 'Say "hello" and nothing else.',
|
|
66
|
-
});
|
|
67
|
-
await done;
|
|
68
|
-
|
|
69
|
-
try {
|
|
70
|
-
const rewindInfo = await client.getRewindInfo({ messageId });
|
|
71
|
-
console.log(
|
|
72
|
-
`Files available to restore: ${rewindInfo.availableFiles.length}`
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
const rewind = await client.executeRewind({
|
|
76
|
-
messageId,
|
|
77
|
-
filesToRestore: [],
|
|
78
|
-
filesToDelete: [],
|
|
79
|
-
forkTitle: 'Rewind example',
|
|
80
|
-
});
|
|
81
|
-
console.log(`Rewound into session: ${rewind.newSessionId}`);
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.log(`Rewind unavailable: ${String(error)}`);
|
|
84
|
-
}
|
|
85
|
-
} finally {
|
|
86
|
-
await client.close();
|
|
87
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tool controls example.
|
|
3
|
-
*
|
|
4
|
-
* Usage:
|
|
5
|
-
* npx tsx examples/tool-controls.ts
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { createSession } from '@factory/droid-sdk';
|
|
9
|
-
|
|
10
|
-
const session = await createSession({
|
|
11
|
-
apiKey: process.env.FACTORY_API_KEY!,
|
|
12
|
-
cwd: process.cwd(),
|
|
13
|
-
enabledToolIds: ['Read', 'Grep'],
|
|
14
|
-
disabledToolIds: ['Execute'],
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
try {
|
|
18
|
-
const before = await session.listTools();
|
|
19
|
-
console.log(
|
|
20
|
-
before.tools
|
|
21
|
-
.filter((tool) => ['Read', 'Execute'].includes(tool.llmId))
|
|
22
|
-
.map((tool) => `${tool.llmId}: ${String(tool.currentlyAllowed)}`)
|
|
23
|
-
.join('\n')
|
|
24
|
-
);
|
|
25
|
-
|
|
26
|
-
await session.updateSettings({ disabledToolIds: ['Read', 'Execute'] });
|
|
27
|
-
|
|
28
|
-
const after = await session.listTools();
|
|
29
|
-
console.log(
|
|
30
|
-
after.tools
|
|
31
|
-
.filter((tool) => ['Read', 'Execute'].includes(tool.llmId))
|
|
32
|
-
.map((tool) => `${tool.llmId}: ${String(tool.currentlyAllowed)}`)
|
|
33
|
-
.join('\n')
|
|
34
|
-
);
|
|
35
|
-
} finally {
|
|
36
|
-
await session.close();
|
|
37
|
-
}
|