@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.
Files changed (92) hide show
  1. package/README.md +35 -482
  2. package/dist/chunk-4G2RKM2H.js +25831 -0
  3. package/dist/chunk-4G2RKM2H.js.map +1 -0
  4. package/dist/chunk-ROFAQUG4.mjs +25831 -0
  5. package/dist/chunk-ROFAQUG4.mjs.map +1 -0
  6. package/dist/{index-CwXX5IUH.d.cts → index-_nUPGHpH.d.mts} +92630 -79659
  7. package/dist/{index-CwXX5IUH.d.ts → index-_nUPGHpH.d.ts} +92630 -79659
  8. package/dist/index.d.mts +4 -0
  9. package/dist/index.d.ts +4 -93103
  10. package/dist/index.js +829 -11745
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +830 -0
  13. package/dist/index.mjs.map +1 -0
  14. package/dist/node.d.mts +757 -0
  15. package/dist/node.d.ts +757 -0
  16. package/dist/node.js +4731 -0
  17. package/dist/node.js.map +1 -0
  18. package/dist/node.mjs +4731 -0
  19. package/dist/node.mjs.map +1 -0
  20. package/docs/typescript-sdk-reference.md +1437 -0
  21. package/examples/browser/daemon-lifecycle.ts +95 -0
  22. package/examples/browser/daemon-model-discovery.ts +47 -0
  23. package/examples/browser/daemon-multi-session.ts +66 -0
  24. package/examples/browser/daemon-session.ts +73 -0
  25. package/examples/browser/index.html +69 -0
  26. package/examples/browser/list-sessions.ts +50 -0
  27. package/examples/node/abort-session-stream.ts +34 -0
  28. package/examples/node/ask-user-elicitation.ts +39 -0
  29. package/examples/node/compact-session.ts +63 -0
  30. package/examples/node/custom-system-prompt.ts +35 -0
  31. package/examples/node/document-input.ts +58 -0
  32. package/examples/node/enter-spec-mode.ts +87 -0
  33. package/examples/node/external-mcp.ts +45 -0
  34. package/examples/node/fork-session.ts +56 -0
  35. package/examples/node/hook-execution.ts +94 -0
  36. package/examples/node/image-attachment.ts +41 -0
  37. package/examples/node/init-metadata.ts +24 -0
  38. package/examples/node/interrupt-session.ts +55 -0
  39. package/examples/node/list-sessions.ts +20 -0
  40. package/examples/node/model-discovery.ts +28 -0
  41. package/examples/node/model-selection.ts +35 -0
  42. package/examples/node/multi-turn-session.ts +37 -0
  43. package/examples/node/observability.ts +75 -0
  44. package/examples/node/partial-stream.ts +56 -0
  45. package/examples/node/permission-handler.ts +60 -0
  46. package/examples/node/rename-session.ts +33 -0
  47. package/examples/node/result-metadata.ts +43 -0
  48. package/examples/node/resume-session.ts +41 -0
  49. package/examples/node/rewind-session.ts +79 -0
  50. package/examples/node/run.ts +32 -0
  51. package/examples/node/sdk-mcp-tool.ts +56 -0
  52. package/examples/node/session-settings.ts +35 -0
  53. package/examples/node/session-stream.ts +59 -0
  54. package/examples/node/skills.ts +24 -0
  55. package/examples/node/spec-mode-new-session.ts +120 -0
  56. package/examples/node/spec-mode-same-session.ts +119 -0
  57. package/examples/node/structured-output.ts +96 -0
  58. package/examples/node/tool-controls.ts +26 -0
  59. package/examples/package.json +3 -0
  60. package/package.json +20 -42
  61. package/dist/index.cjs +0 -12135
  62. package/dist/index.cjs.map +0 -1
  63. package/dist/index.d.cts +0 -93103
  64. package/dist/protocol/index.cjs +0 -6466
  65. package/dist/protocol/index.cjs.map +0 -1
  66. package/dist/protocol/index.d.cts +0 -2
  67. package/dist/protocol/index.d.ts +0 -2
  68. package/dist/protocol/index.js +0 -6078
  69. package/dist/protocol/index.js.map +0 -1
  70. package/docs/daemon-usage-guide.md +0 -544
  71. package/docs/sdk-usage-guide.md +0 -748
  72. package/examples/abort-session-stream.ts +0 -34
  73. package/examples/daemon-multi-session.ts +0 -67
  74. package/examples/droid-dev-structured-output.ts +0 -44
  75. package/examples/fork-session.ts +0 -68
  76. package/examples/hook-execution.ts +0 -68
  77. package/examples/init-metadata.ts +0 -24
  78. package/examples/interrupt-session.ts +0 -35
  79. package/examples/list-sessions.ts +0 -19
  80. package/examples/multi-turn-session.ts +0 -40
  81. package/examples/permission-handler.ts +0 -41
  82. package/examples/readme-structured-output.ts +0 -26
  83. package/examples/result-metadata.ts +0 -63
  84. package/examples/run.ts +0 -39
  85. package/examples/sdk-mcp-tool.ts +0 -44
  86. package/examples/session-stream.ts +0 -57
  87. package/examples/spec-mode-new-session.ts +0 -61
  88. package/examples/spec-mode-same-session.ts +0 -72
  89. package/examples/structured-output.ts +0 -60
  90. package/examples/test-compact.ts +0 -65
  91. package/examples/test-rewind.ts +0 -87
  92. 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
- });
@@ -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
- });
@@ -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
- }