@pleaseai/work 0.1.5 → 0.1.6
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 +12 -0
- package/dist/index.js +120 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -165,6 +165,7 @@ agent:
|
|
|
165
165
|
|
|
166
166
|
claude:
|
|
167
167
|
permission_mode: acceptEdits
|
|
168
|
+
# setting_sources: [] # default: [project, local, user]; set [] for SDK isolation mode
|
|
168
169
|
turn_timeout_ms: 3600000
|
|
169
170
|
---
|
|
170
171
|
|
|
@@ -224,6 +225,7 @@ agent:
|
|
|
224
225
|
|
|
225
226
|
claude:
|
|
226
227
|
permission_mode: acceptEdits
|
|
228
|
+
# setting_sources: [] # default: [project, local, user]; set [] for SDK isolation mode
|
|
227
229
|
turn_timeout_ms: 3600000
|
|
228
230
|
---
|
|
229
231
|
|
|
@@ -287,6 +289,7 @@ agent:
|
|
|
287
289
|
|
|
288
290
|
claude:
|
|
289
291
|
permission_mode: acceptEdits
|
|
292
|
+
# setting_sources: [] # default: [project, local, user]; set [] for SDK isolation mode
|
|
290
293
|
turn_timeout_ms: 3600000
|
|
291
294
|
---
|
|
292
295
|
|
|
@@ -394,9 +397,18 @@ claude:
|
|
|
394
397
|
- Read
|
|
395
398
|
- Write
|
|
396
399
|
- Bash
|
|
400
|
+
setting_sources: # Optional: filesystem settings to load. Default: [project, local, user]
|
|
401
|
+
- project # load .claude/settings.json + CLAUDE.md from the workspace directory
|
|
402
|
+
- local # load .claude/settings.local.json from the workspace directory
|
|
403
|
+
- user # load ~/.claude/settings.json + global CLAUDE.md
|
|
404
|
+
# Only "project", "local", and "user" are valid — other values are ignored
|
|
397
405
|
turn_timeout_ms: 3600000 # Optional: per-turn timeout in ms, default 3600000
|
|
398
406
|
read_timeout_ms: 5000 # Optional: initial subprocess read timeout in ms, default 5000
|
|
399
407
|
stall_timeout_ms: 300000 # Optional: stall detection timeout, default 300000
|
|
408
|
+
settings:
|
|
409
|
+
attribution:
|
|
410
|
+
commit: "🙏 Generated with [Work Please](https://github.com/pleaseai/work-please)" # Optional: appended to git commit messages. Defaults to Work Please link.
|
|
411
|
+
pr: "🙏 Generated with [Work Please](https://github.com/pleaseai/work-please)" # Optional: appended to PR descriptions. Defaults to Work Please link.
|
|
400
412
|
|
|
401
413
|
server:
|
|
402
414
|
port: 3000 # Optional: enable HTTP dashboard on this port
|
package/dist/index.js
CHANGED
|
@@ -2166,7 +2166,7 @@ var {
|
|
|
2166
2166
|
var package_default = {
|
|
2167
2167
|
name: "@pleaseai/work",
|
|
2168
2168
|
type: "module",
|
|
2169
|
-
version: "0.1.
|
|
2169
|
+
version: "0.1.6",
|
|
2170
2170
|
description: "Symphony-spec orchestrator for Claude Code + Asana/GitHub Projects v2",
|
|
2171
2171
|
license: "FSL-1.1-MIT",
|
|
2172
2172
|
repository: {
|
|
@@ -3088,6 +3088,13 @@ agent:
|
|
|
3088
3088
|
max_turns: 20
|
|
3089
3089
|
claude:
|
|
3090
3090
|
permission_mode: bypassPermissions
|
|
3091
|
+
# claude.settings controls the attribution text written into .claude/settings.local.json
|
|
3092
|
+
# of each workspace. Omit to use the default Work Please attribution.
|
|
3093
|
+
# claude:
|
|
3094
|
+
# settings:
|
|
3095
|
+
# attribution:
|
|
3096
|
+
# commit: "\uD83D\uDE4F Generated with Work Please"
|
|
3097
|
+
# pr: "\uD83D\uDE4F Generated with Work Please"
|
|
3091
3098
|
# server:
|
|
3092
3099
|
# port: 3000
|
|
3093
3100
|
---
|
|
@@ -31679,7 +31686,11 @@ function createToolsMcpServer(config2) {
|
|
|
31679
31686
|
}
|
|
31680
31687
|
|
|
31681
31688
|
// src/agent-runner.ts
|
|
31689
|
+
var UUID_PATTERN = /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/i;
|
|
31690
|
+
var NEWLINE_PATTERN = /[\r\n]/g;
|
|
31691
|
+
|
|
31682
31692
|
class AppServerClient {
|
|
31693
|
+
assignedSessionId = null;
|
|
31683
31694
|
sessionId = null;
|
|
31684
31695
|
abortController = null;
|
|
31685
31696
|
workspace;
|
|
@@ -31690,11 +31701,20 @@ class AppServerClient {
|
|
|
31690
31701
|
this.workspace = workspace;
|
|
31691
31702
|
this.queryFn = queryFn;
|
|
31692
31703
|
}
|
|
31693
|
-
async startSession() {
|
|
31704
|
+
async startSession(sessionId) {
|
|
31705
|
+
this.assignedSessionId = null;
|
|
31706
|
+
this.sessionId = null;
|
|
31707
|
+
if (sessionId !== undefined && !UUID_PATTERN.test(sessionId)) {
|
|
31708
|
+
const preview = String(sessionId).slice(0, 64).replace(NEWLINE_PATTERN, " ");
|
|
31709
|
+
return new Error(`invalid_session_id: expected UUID format, got "${preview}"`);
|
|
31710
|
+
}
|
|
31694
31711
|
const validationErr = this.validateWorkspaceCwd();
|
|
31695
31712
|
if (validationErr)
|
|
31696
31713
|
return validationErr;
|
|
31697
|
-
|
|
31714
|
+
const id = sessionId ?? randomUUID();
|
|
31715
|
+
this.assignedSessionId = id;
|
|
31716
|
+
this.sessionId = sessionId ?? null;
|
|
31717
|
+
return { sessionId: id, workspace: this.workspace };
|
|
31698
31718
|
}
|
|
31699
31719
|
async runTurn(session, prompt, _issue, onMessage) {
|
|
31700
31720
|
const controller = new AbortController;
|
|
@@ -31713,6 +31733,8 @@ class AppServerClient {
|
|
|
31713
31733
|
}
|
|
31714
31734
|
if (this.sessionId) {
|
|
31715
31735
|
options.resume = this.sessionId;
|
|
31736
|
+
} else if (this.assignedSessionId) {
|
|
31737
|
+
options.sessionId = this.assignedSessionId;
|
|
31716
31738
|
}
|
|
31717
31739
|
if (this.config.claude.command !== "claude") {
|
|
31718
31740
|
options.pathToClaudeCodeExecutable = this.config.claude.command;
|
|
@@ -31720,12 +31742,21 @@ class AppServerClient {
|
|
|
31720
31742
|
if (this.config.claude.model) {
|
|
31721
31743
|
options.model = this.config.claude.model;
|
|
31722
31744
|
}
|
|
31745
|
+
const sp = this.config.claude.system_prompt;
|
|
31746
|
+
if (sp.type === "custom") {
|
|
31747
|
+
options.systemPrompt = sp.value;
|
|
31748
|
+
} else {
|
|
31749
|
+
options.systemPrompt = sp;
|
|
31750
|
+
}
|
|
31723
31751
|
const toolSpecs = getToolSpecs(this.config);
|
|
31724
31752
|
if (toolSpecs.length > 0) {
|
|
31725
31753
|
options.mcpServers = {
|
|
31726
31754
|
"work-please-tools": createToolsMcpServer(this.config)
|
|
31727
31755
|
};
|
|
31728
31756
|
}
|
|
31757
|
+
if (this.config.claude.setting_sources.length > 0) {
|
|
31758
|
+
options.settingSources = this.config.claude.setting_sources;
|
|
31759
|
+
}
|
|
31729
31760
|
const turnId = randomUUID();
|
|
31730
31761
|
let sessionId = null;
|
|
31731
31762
|
let gotError = false;
|
|
@@ -31737,11 +31768,11 @@ class AppServerClient {
|
|
|
31737
31768
|
const initMsg = msg;
|
|
31738
31769
|
sessionId = initMsg.session_id;
|
|
31739
31770
|
this.sessionId = sessionId;
|
|
31771
|
+
this.assignedSessionId = null;
|
|
31740
31772
|
onMessage({
|
|
31741
31773
|
event: "session_started",
|
|
31742
31774
|
timestamp: new Date,
|
|
31743
31775
|
session_id: sessionId,
|
|
31744
|
-
thread_id: session.threadId,
|
|
31745
31776
|
turn_id: turnId
|
|
31746
31777
|
});
|
|
31747
31778
|
} else if (msg.type === "result") {
|
|
@@ -31794,12 +31825,18 @@ class AppServerClient {
|
|
|
31794
31825
|
});
|
|
31795
31826
|
return err;
|
|
31796
31827
|
}
|
|
31797
|
-
return {
|
|
31828
|
+
return { turn_id: turnId, session_id: sessionId };
|
|
31798
31829
|
} catch (err) {
|
|
31799
31830
|
clearTimeout(timeoutHandle);
|
|
31800
31831
|
const error48 = err instanceof Error ? err : new Error(String(err));
|
|
31832
|
+
if (!sessionId) {
|
|
31833
|
+
if (!options.resume) {
|
|
31834
|
+
this.sessionId = null;
|
|
31835
|
+
this.assignedSessionId = null;
|
|
31836
|
+
}
|
|
31837
|
+
}
|
|
31801
31838
|
onMessage({
|
|
31802
|
-
event: "startup_failed",
|
|
31839
|
+
event: sessionId ? "turn_failed" : "startup_failed",
|
|
31803
31840
|
timestamp: new Date,
|
|
31804
31841
|
payload: { reason: error48.message }
|
|
31805
31842
|
});
|
|
@@ -31808,6 +31845,7 @@ class AppServerClient {
|
|
|
31808
31845
|
}
|
|
31809
31846
|
stopSession() {
|
|
31810
31847
|
this.abortController?.abort();
|
|
31848
|
+
this.assignedSessionId = null;
|
|
31811
31849
|
this.sessionId = null;
|
|
31812
31850
|
this.abortController = null;
|
|
31813
31851
|
}
|
|
@@ -31828,6 +31866,7 @@ import { tmpdir } from "os";
|
|
|
31828
31866
|
import { join, sep as sep2 } from "path";
|
|
31829
31867
|
import process4 from "process";
|
|
31830
31868
|
var ENV_VAR_RE = /^\$([A-Z_]\w*)$/i;
|
|
31869
|
+
var VALID_SETTING_SOURCES = new Set(["user", "project", "local"]);
|
|
31831
31870
|
var DEFAULTS2 = {
|
|
31832
31871
|
POLL_INTERVAL_MS: 30000,
|
|
31833
31872
|
WORKSPACE_ROOT: join(tmpdir(), "work-please_workspaces"),
|
|
@@ -31838,6 +31877,7 @@ var DEFAULTS2 = {
|
|
|
31838
31877
|
CLAUDE_COMMAND: "claude",
|
|
31839
31878
|
CLAUDE_PERMISSION_MODE: "bypassPermissions",
|
|
31840
31879
|
CLAUDE_ALLOWED_TOOLS: [],
|
|
31880
|
+
CLAUDE_SETTING_SOURCES: ["project", "local", "user"],
|
|
31841
31881
|
CLAUDE_TURN_TIMEOUT_MS: 3600000,
|
|
31842
31882
|
CLAUDE_READ_TIMEOUT_MS: 5000,
|
|
31843
31883
|
CLAUDE_STALL_TIMEOUT_MS: 300000,
|
|
@@ -31879,20 +31919,33 @@ function buildConfig(workflow) {
|
|
|
31879
31919
|
max_retry_backoff_ms: posIntValue(agent.max_retry_backoff_ms, DEFAULTS2.MAX_RETRY_BACKOFF_MS),
|
|
31880
31920
|
max_concurrent_agents_by_state: stateLimitsValue(agent.max_concurrent_agents_by_state)
|
|
31881
31921
|
},
|
|
31882
|
-
claude:
|
|
31883
|
-
model: stringValue(claude.model),
|
|
31884
|
-
command: commandValue(claude.command) ?? DEFAULTS2.CLAUDE_COMMAND,
|
|
31885
|
-
permission_mode: stringValue(claude.permission_mode) ?? DEFAULTS2.CLAUDE_PERMISSION_MODE,
|
|
31886
|
-
allowed_tools: stringArrayValue(claude.allowed_tools, DEFAULTS2.CLAUDE_ALLOWED_TOOLS),
|
|
31887
|
-
turn_timeout_ms: intValue(claude.turn_timeout_ms, DEFAULTS2.CLAUDE_TURN_TIMEOUT_MS),
|
|
31888
|
-
read_timeout_ms: intValue(claude.read_timeout_ms, DEFAULTS2.CLAUDE_READ_TIMEOUT_MS),
|
|
31889
|
-
stall_timeout_ms: intValue(claude.stall_timeout_ms, DEFAULTS2.CLAUDE_STALL_TIMEOUT_MS)
|
|
31890
|
-
},
|
|
31922
|
+
claude: buildClaudeConfig(claude),
|
|
31891
31923
|
server: {
|
|
31892
31924
|
port: nonNegIntOrNull(server.port)
|
|
31893
31925
|
}
|
|
31894
31926
|
};
|
|
31895
31927
|
}
|
|
31928
|
+
function buildClaudeConfig(claude) {
|
|
31929
|
+
const settingsSec = sectionMap(claude, "settings");
|
|
31930
|
+
const attributionSec = sectionMap(settingsSec, "attribution");
|
|
31931
|
+
return {
|
|
31932
|
+
model: stringValue(claude.model),
|
|
31933
|
+
command: commandValue(claude.command) ?? DEFAULTS2.CLAUDE_COMMAND,
|
|
31934
|
+
permission_mode: stringValue(claude.permission_mode) ?? DEFAULTS2.CLAUDE_PERMISSION_MODE,
|
|
31935
|
+
allowed_tools: stringArrayValue(claude.allowed_tools, DEFAULTS2.CLAUDE_ALLOWED_TOOLS),
|
|
31936
|
+
setting_sources: stringArrayValue(claude.setting_sources, DEFAULTS2.CLAUDE_SETTING_SOURCES).filter((s2) => VALID_SETTING_SOURCES.has(s2)),
|
|
31937
|
+
turn_timeout_ms: intValue(claude.turn_timeout_ms, DEFAULTS2.CLAUDE_TURN_TIMEOUT_MS),
|
|
31938
|
+
read_timeout_ms: intValue(claude.read_timeout_ms, DEFAULTS2.CLAUDE_READ_TIMEOUT_MS),
|
|
31939
|
+
stall_timeout_ms: intValue(claude.stall_timeout_ms, DEFAULTS2.CLAUDE_STALL_TIMEOUT_MS),
|
|
31940
|
+
system_prompt: systemPromptValue(claude.system_prompt),
|
|
31941
|
+
settings: {
|
|
31942
|
+
attribution: {
|
|
31943
|
+
commit: stringValue(attributionSec.commit),
|
|
31944
|
+
pr: stringValue(attributionSec.pr)
|
|
31945
|
+
}
|
|
31946
|
+
}
|
|
31947
|
+
};
|
|
31948
|
+
}
|
|
31896
31949
|
function buildTrackerConfig(kind, tracker) {
|
|
31897
31950
|
const label_prefix = stringValue(tracker.label_prefix) ?? null;
|
|
31898
31951
|
const filter = buildFilterConfig(sectionMap(tracker, "filter"));
|
|
@@ -32006,6 +32059,26 @@ function maxConcurrentForState(config2, state) {
|
|
|
32006
32059
|
const byState = config2.agent.max_concurrent_agents_by_state;
|
|
32007
32060
|
return byState[normalized] ?? config2.agent.max_concurrent_agents;
|
|
32008
32061
|
}
|
|
32062
|
+
var DEFAULT_SYSTEM_PROMPT = { type: "preset", preset: "claude_code" };
|
|
32063
|
+
function systemPromptValue(val) {
|
|
32064
|
+
if (val == null)
|
|
32065
|
+
return DEFAULT_SYSTEM_PROMPT;
|
|
32066
|
+
if (typeof val === "string") {
|
|
32067
|
+
const trimmed = val.trim();
|
|
32068
|
+
return trimmed ? { type: "custom", value: trimmed } : DEFAULT_SYSTEM_PROMPT;
|
|
32069
|
+
}
|
|
32070
|
+
if (typeof val === "object" && !Array.isArray(val)) {
|
|
32071
|
+
const obj = val;
|
|
32072
|
+
if (obj.type === "preset" && obj.preset === "claude_code") {
|
|
32073
|
+
return typeof obj.append === "string" ? { type: "preset", preset: "claude_code", append: obj.append } : { type: "preset", preset: "claude_code" };
|
|
32074
|
+
}
|
|
32075
|
+
if (obj.type === "custom" && typeof obj.value === "string") {
|
|
32076
|
+
const trimmed = obj.value.trim();
|
|
32077
|
+
return trimmed ? { type: "custom", value: trimmed } : DEFAULT_SYSTEM_PROMPT;
|
|
32078
|
+
}
|
|
32079
|
+
}
|
|
32080
|
+
return DEFAULT_SYSTEM_PROMPT;
|
|
32081
|
+
}
|
|
32009
32082
|
function sectionMap(raw, key) {
|
|
32010
32083
|
const val = raw[key];
|
|
32011
32084
|
return val && typeof val === "object" && !Array.isArray(val) ? val : {};
|
|
@@ -32070,7 +32143,7 @@ function csvValue(val) {
|
|
|
32070
32143
|
function stringArrayValue(val, fallback) {
|
|
32071
32144
|
if (!Array.isArray(val))
|
|
32072
32145
|
return fallback;
|
|
32073
|
-
return val.filter((v) => typeof v === "string");
|
|
32146
|
+
return val.filter((v) => typeof v === "string" && v.trim().length > 0);
|
|
32074
32147
|
}
|
|
32075
32148
|
function stateLimitsValue(val) {
|
|
32076
32149
|
if (!val || typeof val !== "object" || Array.isArray(val))
|
|
@@ -40173,9 +40246,28 @@ function isWorkflowError(result) {
|
|
|
40173
40246
|
}
|
|
40174
40247
|
|
|
40175
40248
|
// src/workspace.ts
|
|
40176
|
-
import { existsSync as existsSync4, lstatSync as lstatSync2, mkdirSync as mkdirSync2, rmSync as rmSync2, statSync as statSync3 } from "fs";
|
|
40177
|
-
import { join as join4, resolve as resolve4, sep as sep4 } from "path";
|
|
40249
|
+
import { existsSync as existsSync4, lstatSync as lstatSync2, mkdirSync as mkdirSync2, rmSync as rmSync2, statSync as statSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
40250
|
+
import { dirname as dirname2, join as join4, resolve as resolve4, sep as sep4 } from "path";
|
|
40178
40251
|
import process6 from "process";
|
|
40252
|
+
var CLAUDE_SETTINGS_PATH = ".claude/settings.local.json";
|
|
40253
|
+
var WORK_PLEASE_URL = "https://github.com/pleaseai/work-please";
|
|
40254
|
+
var ATTRIBUTION_TEXT = `\uD83D\uDE4F Generated with [Work Please](${WORK_PLEASE_URL})`;
|
|
40255
|
+
function generateClaudeSettings(attribution) {
|
|
40256
|
+
return `${JSON.stringify({
|
|
40257
|
+
attribution: {
|
|
40258
|
+
commit: attribution?.commit ?? ATTRIBUTION_TEXT,
|
|
40259
|
+
pr: attribution?.pr ?? ATTRIBUTION_TEXT
|
|
40260
|
+
}
|
|
40261
|
+
}, null, 2)}
|
|
40262
|
+
`;
|
|
40263
|
+
}
|
|
40264
|
+
function ensureClaudeSettings(wsPath, attribution) {
|
|
40265
|
+
const settingsPath = join4(wsPath, CLAUDE_SETTINGS_PATH);
|
|
40266
|
+
if (existsSync4(settingsPath))
|
|
40267
|
+
return;
|
|
40268
|
+
mkdirSync2(dirname2(settingsPath), { recursive: true });
|
|
40269
|
+
writeFileSync2(settingsPath, generateClaudeSettings(attribution), "utf-8");
|
|
40270
|
+
}
|
|
40179
40271
|
var _git = {
|
|
40180
40272
|
spawnSync: (args) => Bun.spawnSync(args)
|
|
40181
40273
|
};
|
|
@@ -40308,6 +40400,11 @@ async function createWorkspace(config2, identifier, issue2) {
|
|
|
40308
40400
|
if (hookErr)
|
|
40309
40401
|
return hookErr;
|
|
40310
40402
|
}
|
|
40403
|
+
try {
|
|
40404
|
+
ensureClaudeSettings(wtPath, config2.claude.settings.attribution);
|
|
40405
|
+
} catch (err) {
|
|
40406
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
40407
|
+
}
|
|
40311
40408
|
return { path: wtPath, workspace_key: key, created_now: createdNow };
|
|
40312
40409
|
}
|
|
40313
40410
|
}
|
|
@@ -40338,6 +40435,11 @@ async function createWorkspace(config2, identifier, issue2) {
|
|
|
40338
40435
|
if (hookErr)
|
|
40339
40436
|
return hookErr;
|
|
40340
40437
|
}
|
|
40438
|
+
try {
|
|
40439
|
+
ensureClaudeSettings(wsPath, config2.claude.settings.attribution);
|
|
40440
|
+
} catch (err) {
|
|
40441
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
40442
|
+
}
|
|
40341
40443
|
return workspace;
|
|
40342
40444
|
}
|
|
40343
40445
|
async function removeWorkspace(config2, identifier, issue2) {
|