@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 +1 -1
- package/dist/bucket/server-messages.d.ts +3 -2
- package/dist/dust.js +76 -11
- package/package.json +1 -1
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
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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}`);
|