@joshski/dust 0.1.107 → 0.1.108

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/artifacts.js CHANGED
@@ -866,7 +866,7 @@ async function createRefineIdeaTask(fileSystem, dustPath, ideaSlug, description,
866
866
  }
867
867
  async function decomposeIdea(fileSystem, dustPath, options, dustCommand) {
868
868
  const cmd = dustCommand ?? "dust";
869
- return createIdeaTransitionTask(fileSystem, dustPath, "decompose", "Decompose Idea: ", options.ideaSlug, (ideaTitle) => `Create one or more well-defined tasks from this idea. Prefer smaller, narrowly scoped tasks that each deliver a thin but complete vertical slice of working software -- a path through the system that can be tested end-to-end -- rather than component-oriented tasks (like "add schema" or "build endpoint") that only work once all tasks are done. Split the idea into multiple tasks if it covers more than one logical change. Run \`${cmd} principles\` to link relevant principles and \`${cmd} facts\` for design decisions that should inform the task. See [${ideaTitle}](../ideas/${options.ideaSlug}.md).`, [
869
+ return createIdeaTransitionTask(fileSystem, dustPath, "decompose", "Decompose Idea: ", options.ideaSlug, (ideaTitle) => `Create one or more well-defined tasks from this idea. Prefer smaller, narrowly scoped tasks that each deliver a thin but complete vertical slice of working software -- a path through the system that can be tested end-to-end -- rather than component-oriented tasks (like "add schema" or "build endpoint") that only work once all tasks are done. Split the idea into multiple tasks if it covers more than one logical change. Run \`${cmd} principles\` to identify relevant principles (both core and local), then inline the FULL content of ALL selected principles in a Guidance section in each new task file (after Principles but before Definition of Done). This ensures implementing agents read the guidance without extra tool calls. Also run \`${cmd} facts\` for design decisions that should inform the task. See [${ideaTitle}](../ideas/${options.ideaSlug}.md).`, [
870
870
  "One or more new tasks are created in .dust/tasks/",
871
871
  "Task's Principles section links to relevant principles from .dust/principles/",
872
872
  `The original idea (.dust/ideas/${options.ideaSlug}.md) is deleted or updated to reflect remaining scope`
@@ -34,13 +34,14 @@ export interface ToolDefinitionsMessage {
34
34
  }
35
35
  /**
36
36
  * Sent by client on connect to initiate the handshake.
37
- * Includes version, platform, git remote, and agent capabilities.
37
+ * Includes version, platform, git remote, machine ID, and agent capabilities.
38
38
  */
39
39
  export interface ConnectionInitMessage {
40
40
  type: 'connection-init';
41
41
  dustVersion: string;
42
42
  platform: string;
43
43
  gitRemote?: string;
44
+ machineId?: string;
44
45
  agents: AgentCapability[];
45
46
  }
46
47
  /**
@@ -71,4 +72,4 @@ export declare function parseServerMessage(data: unknown): ServerMessage | null;
71
72
  * Build a ConnectionInitMessage payload.
72
73
  * Pure function - no side effects.
73
74
  */
74
- export declare function buildConnectionInitPayload(dustVersion: string, platform: string, gitRemote: string | undefined, agents: AgentCapability[]): ConnectionInitMessage;
75
+ export declare function buildConnectionInitPayload(dustVersion: string, platform: string, gitRemote: string | undefined, agents: AgentCapability[], machineId?: string): ConnectionInitMessage;
package/dist/dust.js CHANGED
@@ -7,7 +7,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
7
7
  var require_package = __commonJS((exports, module) => {
8
8
  module.exports = {
9
9
  name: "@joshski/dust",
10
- version: "0.1.107",
10
+ version: "0.1.108",
11
11
  description: "Flow state for AI coding agents",
12
12
  type: "module",
13
13
  bin: {
@@ -711,7 +711,7 @@ async function loadSettings(cwd, fileSystem, runtime) {
711
711
  }
712
712
 
713
713
  // lib/version.ts
714
- var DUST_VERSION = "0.1.107";
714
+ var DUST_VERSION = "0.1.108";
715
715
 
716
716
  // lib/cli/middleware.ts
717
717
  function applyMiddleware(middlewares, execute) {
@@ -8238,7 +8238,7 @@ function parseServerMessage(data) {
8238
8238
  const parser = messageParsers[messageType];
8239
8239
  return parser ? parser(message) : null;
8240
8240
  }
8241
- function buildConnectionInitPayload(dustVersion, platform, gitRemote, agents) {
8241
+ function buildConnectionInitPayload(dustVersion, platform, gitRemote, agents, machineId) {
8242
8242
  const message = {
8243
8243
  type: "connection-init",
8244
8244
  dustVersion,
@@ -8248,6 +8248,9 @@ function buildConnectionInitPayload(dustVersion, platform, gitRemote, agents) {
8248
8248
  if (gitRemote !== undefined) {
8249
8249
  message.gitRemote = gitRemote;
8250
8250
  }
8251
+ if (machineId !== undefined) {
8252
+ message.machineId = machineId;
8253
+ }
8251
8254
  return message;
8252
8255
  }
8253
8256
 
@@ -8775,6 +8778,7 @@ import { EventEmitter } from "node:events";
8775
8778
  import { accessSync, statSync } from "node:fs";
8776
8779
  import { chmod, mkdir, readdir, readFile, writeFile } from "node:fs/promises";
8777
8780
  import { homedir as homedir2, platform, release } from "node:os";
8781
+ import { join as join10 } from "node:path";
8778
8782
 
8779
8783
  // lib/bucket/auth-server.ts
8780
8784
  import { createServer as httpCreateServer3 } from "node:http";
@@ -9069,12 +9073,44 @@ async function getGitRemote(spawn2) {
9069
9073
  async function defaultBuildConnectionInit(spawn2) {
9070
9074
  const dustVersion = getDustVersion();
9071
9075
  const platformStr = getPlatformString();
9072
- const [gitRemote, capabilitiesMessage] = await Promise.all([
9076
+ const io = {
9077
+ getEnv: (key) => process.env[key],
9078
+ readFile,
9079
+ getHostname: () => __require("node:os").hostname()
9080
+ };
9081
+ const [gitRemote, capabilitiesMessage, machineId] = await Promise.all([
9073
9082
  getGitRemote(spawn2),
9074
- discoverAgentCapabilities({ spawn: spawn2 })
9083
+ discoverAgentCapabilities({ spawn: spawn2 }),
9084
+ getMachineId(io)
9075
9085
  ]);
9076
9086
  const agents = capabilitiesMessage.agents;
9077
- return buildConnectionInitPayload(dustVersion, platformStr, gitRemote, agents);
9087
+ return buildConnectionInitPayload(dustVersion, platformStr, gitRemote, agents, machineId);
9088
+ }
9089
+ async function getMachineId(io) {
9090
+ const envMachineId = io.getEnv("DUST_MACHINE_ID");
9091
+ if (envMachineId && envMachineId.trim()) {
9092
+ return envMachineId.trim();
9093
+ }
9094
+ try {
9095
+ const homeDir = homedir2();
9096
+ const machineIdPath = join10(homeDir, ".dust", "machine-id");
9097
+ const fileContent = await io.readFile(machineIdPath, "utf8");
9098
+ const trimmedContent = fileContent.trim();
9099
+ if (trimmedContent) {
9100
+ return trimmedContent;
9101
+ }
9102
+ } catch {}
9103
+ return io.getHostname();
9104
+ }
9105
+ async function storeMachineId(machineId, homeDir, mkdirFn, writeFileFn) {
9106
+ const trimmedId = machineId.trim();
9107
+ if (!trimmedId) {
9108
+ throw new Error("Machine ID cannot be empty or whitespace-only");
9109
+ }
9110
+ const dustDir = join10(homeDir, ".dust");
9111
+ const machineIdPath = join10(dustDir, "machine-id");
9112
+ await mkdirFn(dustDir, { recursive: true });
9113
+ await writeFileFn(machineIdPath, trimmedId, "utf8");
9078
9114
  }
9079
9115
  function createDefaultBucketDependencies() {
9080
9116
  const envConfig = readEnvConfig(process.env);
@@ -9713,7 +9749,26 @@ function parseBucketWorkerArgs(commandArguments) {
9713
9749
  error: "Cannot use both --docker and --apple-container. Choose one container runtime."
9714
9750
  };
9715
9751
  }
9716
- return { success: true, docker, appleContainer };
9752
+ let machineId;
9753
+ const machineIdIndex = commandArguments.indexOf("--machine-id");
9754
+ if (machineIdIndex !== -1) {
9755
+ const machineIdValue = commandArguments[machineIdIndex + 1];
9756
+ if (!machineIdValue || machineIdValue.startsWith("--")) {
9757
+ return {
9758
+ success: false,
9759
+ error: "--machine-id flag requires a value"
9760
+ };
9761
+ }
9762
+ const trimmedValue = machineIdValue.trim();
9763
+ if (!trimmedValue) {
9764
+ return {
9765
+ success: false,
9766
+ error: "Machine ID cannot be empty or whitespace-only"
9767
+ };
9768
+ }
9769
+ machineId = trimmedValue;
9770
+ }
9771
+ return { success: true, docker, appleContainer, machineId };
9717
9772
  }
9718
9773
  async function bucketWorker(dependencies, bucketDeps = createDefaultBucketDependencies()) {
9719
9774
  enableFileLogs("bucket");
@@ -9725,6 +9780,16 @@ async function bucketWorker(dependencies, bucketDeps = createDefaultBucketDepend
9725
9780
  }
9726
9781
  bucketDeps.forceDocker = argsResult.docker;
9727
9782
  bucketDeps.forceAppleContainer = argsResult.appleContainer;
9783
+ if (argsResult.machineId) {
9784
+ try {
9785
+ const { mkdir: mkdir2, writeFile: writeFile2 } = await import("node:fs/promises");
9786
+ const { homedir: homedir3 } = await import("node:os");
9787
+ await storeMachineId(argsResult.machineId, homedir3(), mkdir2, writeFile2);
9788
+ } catch (error) {
9789
+ context.stderr(`Failed to store machine ID: ${error instanceof Error ? error.message : String(error)}`);
9790
+ return { exitCode: 1 };
9791
+ }
9792
+ }
9728
9793
  if (isUnattended(bucketDeps.session)) {
9729
9794
  context.stderr("dust bucket cannot run inside an unattended session (DUST_UNATTENDED is set)");
9730
9795
  return { exitCode: 1 };
@@ -10011,7 +10076,7 @@ Run \`dust bucket tool ${toolName}\` to see available operations.`);
10011
10076
  }
10012
10077
 
10013
10078
  // lib/cli/commands/lint-markdown.ts
10014
- import { isAbsolute, join as join10, relative, sep } from "node:path";
10079
+ import { isAbsolute, join as join11, relative, sep } from "node:path";
10015
10080
 
10016
10081
  // lib/artifacts/index.ts
10017
10082
  var ARTIFACT_TYPES = [
@@ -10740,7 +10805,7 @@ async function lintMarkdown(dependencies) {
10740
10805
  const violations = [];
10741
10806
  context.stdout("Validating directory structure...");
10742
10807
  violations.push(...await validateDirectoryStructure(dustPath, fileSystem));
10743
- const settingsPath = join10(dustPath, "config", "settings.json");
10808
+ const settingsPath = join11(dustPath, "config", "settings.json");
10744
10809
  const settingsResult = await validateSettingsFile(fileSystem, settingsPath);
10745
10810
  if (settingsResult.didValidate) {
10746
10811
  context.stdout("Validating settings.json...");
@@ -13031,7 +13096,7 @@ async function list(dependencies) {
13031
13096
  // lib/loop/loop.ts
13032
13097
  import { existsSync, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2 } from "node:fs";
13033
13098
  import os3 from "node:os";
13034
- import { join as join11 } from "node:path";
13099
+ import { join as join12 } from "node:path";
13035
13100
 
13036
13101
  // lib/loop/parse-args.ts
13037
13102
  var DEFAULT_MAX_ITERATIONS = 10;
@@ -13094,7 +13159,7 @@ async function setupDockerProxies(dockerResult, loopDependencies, sessionId, inc
13094
13159
  const apiProxy = await createClaudeApiProxyServer();
13095
13160
  stopApiProxy = apiProxy.stop;
13096
13161
  const claudeApiProxyUrl = `http://${hostAddress}:${apiProxy.port}`;
13097
- settingsFilePath = join11(os3.tmpdir(), `dust-claude-settings-${sessionId}.json`);
13162
+ settingsFilePath = join12(os3.tmpdir(), `dust-claude-settings-${sessionId}.json`);
13098
13163
  const settingsContent = generateApiKeyHelperSettings(claudeApiProxyUrl);
13099
13164
  writeFileSync2(settingsFilePath, settingsContent, "utf-8");
13100
13165
  log14(`created settings file at ${settingsFilePath}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joshski/dust",
3
- "version": "0.1.107",
3
+ "version": "0.1.108",
4
4
  "description": "Flow state for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {