@rubytech/create-maxy-code 0.1.388 → 0.1.391
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/__tests__/claude-bin.test.js +51 -0
- package/dist/__tests__/claude-upgrade-privilege.test.js +17 -0
- package/dist/__tests__/joblogic-excluded.test.js +39 -0
- package/dist/__tests__/launchd-plist.test.js +36 -1
- package/dist/__tests__/macos-darwin-branch.test.js +18 -0
- package/dist/__tests__/neo4j-datadir.test.js +14 -0
- package/dist/claude-bin.js +78 -0
- package/dist/claude-upgrade-privilege.js +21 -0
- package/dist/index.js +262 -34
- package/dist/launchd-plist.js +25 -9
- package/dist/neo4j-datadir.js +15 -0
- package/package.json +1 -1
- package/payload/platform/config/brand.json +1 -1
- package/payload/platform/plugins/.claude-plugin/marketplace.json +0 -5
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +24 -5
- package/payload/platform/plugins/docs/references/admin-session.md +4 -0
- package/payload/platform/plugins/docs/references/admin-ui.md +18 -1
- package/payload/platform/plugins/docs/references/joblogic.md +2 -0
- package/payload/platform/plugins/whatsapp/references/channels-whatsapp.md +2 -0
- package/payload/platform/plugins/work/PLUGIN.md +3 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.d.ts +2 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.d.ts.map +1 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.js +98 -0
- package/payload/platform/plugins/work/mcp/dist/__tests__/session-metering.test.js.map +1 -0
- package/payload/platform/plugins/work/mcp/dist/index.js +16 -0
- package/payload/platform/plugins/work/mcp/dist/index.js.map +1 -1
- package/payload/platform/plugins/work/mcp/dist/tools/session-metering.d.ts +53 -0
- package/payload/platform/plugins/work/mcp/dist/tools/session-metering.d.ts.map +1 -0
- package/payload/platform/plugins/work/mcp/dist/tools/session-metering.js +80 -0
- package/payload/platform/plugins/work/mcp/dist/tools/session-metering.js.map +1 -0
- package/payload/platform/plugins/work/mcp/package.json +2 -1
- package/payload/platform/scripts/smoke-boot-services.sh +35 -10
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +1 -0
- package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/claude-host-creds.d.ts +11 -0
- package/payload/platform/services/claude-session-manager/dist/claude-host-creds.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/claude-host-creds.js +37 -0
- package/payload/platform/services/claude-session-manager/dist/claude-host-creds.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/http-server.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/http-server.js +98 -8
- package/payload/platform/services/claude-session-manager/dist/http-server.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pricing.d.ts +45 -0
- package/payload/platform/services/claude-session-manager/dist/pricing.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/pricing.js +57 -0
- package/payload/platform/services/claude-session-manager/dist/pricing.js.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js +7 -0
- package/payload/platform/services/claude-session-manager/dist/pty-spawner.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.d.ts.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js +5 -1
- package/payload/platform/services/claude-session-manager/dist/rc-daemon.js.map +1 -1
- package/payload/platform/services/claude-session-manager/dist/session-metering.d.ts +38 -0
- package/payload/platform/services/claude-session-manager/dist/session-metering.d.ts.map +1 -0
- package/payload/platform/services/claude-session-manager/dist/session-metering.js +292 -0
- package/payload/platform/services/claude-session-manager/dist/session-metering.js.map +1 -0
- package/payload/platform/templates/specialists/agents/project-manager.md +1 -1
- package/payload/server/public/assets/{AdminLoginScreens-BejIjbmU.js → AdminLoginScreens-CL27ZV86.js} +1 -1
- package/payload/server/public/assets/AdminShell-CBcSh9Yd.js +1 -0
- package/payload/server/public/assets/{Checkbox-1F1tzqca.js → Checkbox-DRIcYN9r.js} +1 -1
- package/payload/server/public/assets/{Transcript-DkGa4CQH.js → Transcript-CRc72hkG.js} +1 -1
- package/payload/server/public/assets/{admin-DqQARkjy.js → admin-iKYYnv3w.js} +1 -1
- package/payload/server/public/assets/{browser-nDtEK6RC.js → browser--8gzAe-E.js} +1 -1
- package/payload/server/public/assets/calendar-7xAT81N_.js +1 -0
- package/payload/server/public/assets/chat-B8Z9W42Z.js +1 -0
- package/payload/server/public/assets/chevron-left-DDselYau.js +1 -0
- package/payload/server/public/assets/data-Ece320dZ.js +1 -0
- package/payload/server/public/assets/{graph-DFyicKd7.js → graph-B3haz2DN.js} +2 -2
- package/payload/server/public/assets/{graph-labels-D3BQdcpD.js → graph-labels-Ba_fyw6I.js} +1 -1
- package/payload/server/public/assets/{operator-BxrjWdT9.js → operator-BYL1IFz9.js} +1 -1
- package/payload/server/public/assets/page-Bj6lB07z.js +32 -0
- package/payload/server/public/assets/page-CLKVCquw.js +1 -0
- package/payload/server/public/assets/{public-DbdqfdYq.js → public-BKJUKC76.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-BkX8HODe.js → rotate-ccw-BypBbSI4.js} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-4qilMyPX.css +1 -0
- package/payload/server/public/assets/useSubAccountSwitcher-CsRv6MEd.js +9 -0
- package/payload/server/public/browser.html +4 -4
- package/payload/server/public/calendar.html +5 -5
- package/payload/server/public/chat.html +8 -8
- package/payload/server/public/data.html +7 -7
- package/payload/server/public/graph.html +8 -8
- package/payload/server/public/index.html +10 -10
- package/payload/server/public/operator.html +10 -10
- package/payload/server/public/public.html +8 -8
- package/payload/server/server.js +327 -255
- package/payload/platform/plugins/joblogic/.claude-plugin/plugin.json +0 -21
- package/payload/platform/plugins/joblogic/PLUGIN.md +0 -182
- package/payload/platform/plugins/joblogic/lib/mcp-spawn-tee/index.js +0 -193
- package/payload/platform/plugins/joblogic/lib/mcp-spawn-tee/package.json +0 -3
- package/payload/platform/plugins/joblogic/mcp/dist/index.d.ts +0 -2
- package/payload/platform/plugins/joblogic/mcp/dist/index.d.ts.map +0 -1
- package/payload/platform/plugins/joblogic/mcp/dist/index.js +0 -229
- package/payload/platform/plugins/joblogic/mcp/dist/index.js.map +0 -1
- package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.d.ts +0 -31
- package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.d.ts.map +0 -1
- package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.js +0 -78
- package/payload/platform/plugins/joblogic/mcp/dist/lib/auth.js.map +0 -1
- package/payload/platform/plugins/joblogic/mcp/dist/lib/client.d.ts +0 -35
- package/payload/platform/plugins/joblogic/mcp/dist/lib/client.d.ts.map +0 -1
- package/payload/platform/plugins/joblogic/mcp/dist/lib/client.js +0 -106
- package/payload/platform/plugins/joblogic/mcp/dist/lib/client.js.map +0 -1
- package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.d.ts +0 -8
- package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.d.ts.map +0 -1
- package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.js +0 -41
- package/payload/platform/plugins/joblogic/mcp/dist/lib/idempotency.js.map +0 -1
- package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.d.ts +0 -21
- package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.d.ts.map +0 -1
- package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.js +0 -47
- package/payload/platform/plugins/joblogic/mcp/dist/lib/secrets.js.map +0 -1
- package/payload/platform/plugins/joblogic/mcp/package.json +0 -10
- package/payload/platform/plugins/joblogic/skills/joblogic/SKILL.md +0 -32
- package/payload/server/public/assets/AdminShell-D2-uBSB5.js +0 -1
- package/payload/server/public/assets/calendar-CO4Bwmho.js +0 -1
- package/payload/server/public/assets/chat-DeIge_bC.js +0 -1
- package/payload/server/public/assets/chevron-left-DhVdq0aN.js +0 -1
- package/payload/server/public/assets/data-B1GIdzHk.js +0 -1
- package/payload/server/public/assets/page-ByDLq_o1.js +0 -1
- package/payload/server/public/assets/page-D-Ep4bXd.js +0 -32
- package/payload/server/public/assets/useSubAccountSwitcher-DMbRhLPv.js +0 -9
- package/payload/server/public/assets/useSubAccountSwitcher-DS0iqSkP.css +0 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Max time (ms) a spawned claude waits for the host to finish refreshing an
|
|
2
|
+
* expiring token before erroring. The host heartbeat refreshes proactively
|
|
3
|
+
* inside the 5-minute expiry window, so an in-flight refresh at spawn time is
|
|
4
|
+
* rare; 30s is a generous ceiling that never wedges a spawn. */
|
|
5
|
+
export declare const HOST_AUTH_REFRESH_TIMEOUT_MS = "30000";
|
|
6
|
+
/** Mutate `env` in place to enable claude's host-managed credentials-file mode
|
|
7
|
+
* when running on darwin, then return it. No-op on every other platform.
|
|
8
|
+
* `claudeConfigDir` is the brand's `.claude` dir; the credentials file is its
|
|
9
|
+
* `.credentials.json` child. */
|
|
10
|
+
export declare function applyHostCredsEnv(env: NodeJS.ProcessEnv, claudeConfigDir: string, platform?: NodeJS.Platform): NodeJS.ProcessEnv;
|
|
11
|
+
//# sourceMappingURL=claude-host-creds.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-host-creds.d.ts","sourceRoot":"","sources":["../src/claude-host-creds.ts"],"names":[],"mappings":"AAsBA;;;iEAGiE;AACjE,eAAO,MAAM,4BAA4B,UAAU,CAAA;AAEnD;;;iCAGiC;AACjC,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,CAAC,UAAU,EACtB,eAAe,EAAE,MAAM,EACvB,QAAQ,GAAE,MAAM,CAAC,QAA2B,GAC3C,MAAM,CAAC,UAAU,CAMnB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Task 1395 gap 1 — macOS credential-store bridge.
|
|
2
|
+
//
|
|
3
|
+
// On macOS the `claude` CLI stores its OAuth token in the login Keychain,
|
|
4
|
+
// while this platform reads and refreshes the token from a FILE
|
|
5
|
+
// (`<CLAUDE_CONFIG_DIR>/.credentials.json`, the same path the UI server's
|
|
6
|
+
// readCredentials()/writeOAuthCredentials() own). Left alone the two never
|
|
7
|
+
// meet: auth-health reads an empty file and reports `missing` forever.
|
|
8
|
+
//
|
|
9
|
+
// `claude` exposes a host-managed credentials-file mode: point
|
|
10
|
+
// CLAUDE_CODE_HOST_CREDS_FILE at that file and the spawned claude reads/writes
|
|
11
|
+
// the token there instead of the Keychain, and — crucially — does NOT run its
|
|
12
|
+
// own refresh, waiting up to CLAUDE_CODE_HOST_AUTH_REFRESH_TIMEOUT_MS for the
|
|
13
|
+
// host (this platform's auth-health heartbeat) to refresh an expiring token.
|
|
14
|
+
// That keeps a single refresh owner and no double-refresh race.
|
|
15
|
+
//
|
|
16
|
+
// Darwin-only: on Linux `claude` already defaults to the same file under
|
|
17
|
+
// CLAUDE_CONFIG_DIR, so setting host-creds mode there would needlessly switch
|
|
18
|
+
// refresh ownership. The regression boundary is that Linux stays byte-for-byte
|
|
19
|
+
// unchanged.
|
|
20
|
+
import { join } from 'node:path';
|
|
21
|
+
/** Max time (ms) a spawned claude waits for the host to finish refreshing an
|
|
22
|
+
* expiring token before erroring. The host heartbeat refreshes proactively
|
|
23
|
+
* inside the 5-minute expiry window, so an in-flight refresh at spawn time is
|
|
24
|
+
* rare; 30s is a generous ceiling that never wedges a spawn. */
|
|
25
|
+
export const HOST_AUTH_REFRESH_TIMEOUT_MS = '30000';
|
|
26
|
+
/** Mutate `env` in place to enable claude's host-managed credentials-file mode
|
|
27
|
+
* when running on darwin, then return it. No-op on every other platform.
|
|
28
|
+
* `claudeConfigDir` is the brand's `.claude` dir; the credentials file is its
|
|
29
|
+
* `.credentials.json` child. */
|
|
30
|
+
export function applyHostCredsEnv(env, claudeConfigDir, platform = process.platform) {
|
|
31
|
+
if (platform === 'darwin' && claudeConfigDir) {
|
|
32
|
+
env.CLAUDE_CODE_HOST_CREDS_FILE = join(claudeConfigDir, '.credentials.json');
|
|
33
|
+
env.CLAUDE_CODE_HOST_AUTH_REFRESH_TIMEOUT_MS = HOST_AUTH_REFRESH_TIMEOUT_MS;
|
|
34
|
+
}
|
|
35
|
+
return env;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=claude-host-creds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-host-creds.js","sourceRoot":"","sources":["../src/claude-host-creds.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,EAAE;AACF,0EAA0E;AAC1E,gEAAgE;AAChE,0EAA0E;AAC1E,2EAA2E;AAC3E,uEAAuE;AACvE,EAAE;AACF,+DAA+D;AAC/D,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,6EAA6E;AAC7E,gEAAgE;AAChE,EAAE;AACF,yEAAyE;AACzE,8EAA8E;AAC9E,+EAA+E;AAC/E,aAAa;AAEb,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC;;;iEAGiE;AACjE,MAAM,CAAC,MAAM,4BAA4B,GAAG,OAAO,CAAA;AAEnD;;;iCAGiC;AACjC,MAAM,UAAU,iBAAiB,CAC/B,GAAsB,EACtB,eAAuB,EACvB,WAA4B,OAAO,CAAC,QAAQ;IAE5C,IAAI,QAAQ,KAAK,QAAQ,IAAI,eAAe,EAAE,CAAC;QAC7C,GAAG,CAAC,2BAA2B,GAAG,IAAI,CAAC,eAAe,EAAE,mBAAmB,CAAC,CAAA;QAC5E,GAAG,CAAC,wCAAwC,GAAG,4BAA4B,CAAA;IAC7E,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAe3B,OAAO,EAkBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAe3B,OAAO,EAkBL,KAAK,SAAS,EAEf,MAAM,kBAAkB,CAAA;AA6BzB,OAAO,KAAK,EAAE,SAAS,EAAyB,MAAM,iBAAiB,CAAA;AAEvE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAE3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AAyFlE,eAAO,MAAM,kBAAkB,QAA2B,CAAA;AAS1D,eAAO,MAAM,4BAA4B,QAAS,CAAA;AAIlD,MAAM,WAAW,QAAS,SAAQ,IAAI,CAAC,SAAS,EAAE,gBAAgB,GAAG,SAAS,CAAC;IAC7E;;qEAEiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,SAAS,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,WAAW,CAAA;IAC/B,eAAe,EAAE,aAAa,CAAA;IAC9B;kFAC8E;IAC9E,WAAW,EAAE,kBAAkB,CAAA;IAC/B;;gFAE4E;IAC5E,cAAc,EAAE,cAAc,CAAA;IAC9B;;;6BAGyB;IACzB,mBAAmB,CAAC,EAAE,mBAAmB,CAAA;IACzC;;;sCAGkC;IAClC,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;IAC3C;;gFAE4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAsFD;;;;;;mEAMmE;AACnE,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAiC9D;AAMD;;;;;;iBAMiB;AACjB,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAmCvF;AAID;;;;;;yBAMyB;AACzB,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAiCzD;AAkCD,wBAAgB,eAAe,CAAC,aAAa,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAEpG;AAgBD,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE1D;AAUD,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAMvE;AAMD,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,MAAM,CAER;AAkCD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAe5F;AAwJD;;;kEAGkE;AAClE,MAAM,MAAM,OAAO,GAAG,IAAI,GAAG;IAC3B,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACpD;;;+CAG2C;IAC3C,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAChD,CAAA;AA8CD,wBAAgB,YAAY,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CA4vFpD"}
|
|
@@ -27,7 +27,7 @@ import { buildWebchatChannelMcpServers, buildWebchatChannelArgv, webchatChannelM
|
|
|
27
27
|
import { buildTelegramChannelMcpServers, buildTelegramChannelArgv, telegramChannelMcpConfigPath } from './telegram-channel-mcp.js';
|
|
28
28
|
import { buildChannelMcpServers, buildChannelArgv, channelMcpConfigPath } from './channel-mcp.js';
|
|
29
29
|
import { mergeTarget, isMultiTarget, targetKinds } from './channel-targets.js';
|
|
30
|
-
import { randomUUID } from 'node:crypto';
|
|
30
|
+
import { randomUUID, createHash } from 'node:crypto';
|
|
31
31
|
import { execFile, execFileSync } from 'node:child_process';
|
|
32
32
|
import { buildRcChildEnv, reapplyAdminLevers } from './rc-daemon.js';
|
|
33
33
|
import { runConnectorAuthLogin } from './connector-auth.js';
|
|
@@ -44,6 +44,7 @@ import { createRcChildLog } from './rc-child-log.js';
|
|
|
44
44
|
// --append-system-prompt for channel-bound admin sessions.
|
|
45
45
|
import { extractVoiceSection } from './system-prompt.js';
|
|
46
46
|
import { readJsonlSession } from './jsonl-enumerator.js';
|
|
47
|
+
import { computeMetering } from './session-metering.js';
|
|
47
48
|
import { claudeStateRoot, projectSlugForCwd, jsonlPathForSessionId, sidecarPathForSessionId, permissionModeLogPathForSessionId, findExistingJsonlForSessionId, slugForExistingJsonl, jsonlPathForSlug, sidecarPathForSlug, detectRemoteControlSlug, classifyBindBlocker, } from './jsonl-path.js';
|
|
48
49
|
import { basename, dirname, join } from 'node:path';
|
|
49
50
|
import { validateUserTitle } from './user-title-store.js';
|
|
@@ -54,6 +55,15 @@ const CHANNELS = ['browser', 'whatsapp', 'telegram', 'webchat', 'email'];
|
|
|
54
55
|
// sessionId UUID (v4) minted by createNewAdminConversation in
|
|
55
56
|
// platform/ui/app/lib/neo4j-store.ts.
|
|
56
57
|
const UUID_PATTERN = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
58
|
+
// Task 1392 — the WhatsApp-channel launch-param override. Every WhatsApp admin
|
|
59
|
+
// session runs Sonnet 5 / effort max / bypass, overriding the Task 956 fixed admin
|
|
60
|
+
// params (Opus 4.8 / medium, resolved from settings.json). Expressed as an explicit
|
|
61
|
+
// constant set mirroring the rc-daemon `ADMIN_*` shape. Permission mode is already
|
|
62
|
+
// bypassPermissions (settings.json), so only model + effort are asserted here. `max`
|
|
63
|
+
// is session-only and invalid as a settings.json `effortLevel`, so it rides the
|
|
64
|
+
// `--effort max` argv flag, not the inline settings.
|
|
65
|
+
const WHATSAPP_ADMIN_MODEL = SONNET_MODEL;
|
|
66
|
+
const WHATSAPP_ADMIN_EFFORT = 'max';
|
|
57
67
|
function parseAboutOwner(raw) {
|
|
58
68
|
if (!raw || typeof raw !== 'object')
|
|
59
69
|
return undefined;
|
|
@@ -1402,6 +1412,37 @@ export function buildHttpApp(deps) {
|
|
|
1402
1412
|
timed(deps.logger, 'GET', `/${id}/meta`, 200, Date.now() - start);
|
|
1403
1413
|
return c.json(payload, 200);
|
|
1404
1414
|
});
|
|
1415
|
+
// Task 1384 — deterministic per-day usage & GBP cost for one session. Reads
|
|
1416
|
+
// whichever location holds the JSONL (top level or archive subdir), runs the
|
|
1417
|
+
// full-parse metering core (no AI), and returns the summary. The `op=surface`
|
|
1418
|
+
// checksum lets the http and MCP callers be proven to agree on one session.
|
|
1419
|
+
app.get('/:sessionId/metering', async (c) => {
|
|
1420
|
+
const start = Date.now();
|
|
1421
|
+
const id = c.req.param('sessionId');
|
|
1422
|
+
if (!SESSION_ID_PATTERN.test(id)) {
|
|
1423
|
+
timed(deps.logger, 'GET', `/${id}/metering`, 400, Date.now() - start);
|
|
1424
|
+
return c.json({ error: 'invalid-session-id' }, 400);
|
|
1425
|
+
}
|
|
1426
|
+
const row = resolveRow(deps.watcher, id);
|
|
1427
|
+
if (!row) {
|
|
1428
|
+
timed(deps.logger, 'GET', `/${id}/metering`, 404, Date.now() - start);
|
|
1429
|
+
return c.json({ error: 'session-not-found' }, 404);
|
|
1430
|
+
}
|
|
1431
|
+
const topJsonl = jsonlPathForSessionId(deps.spawnCwd, row.sessionId);
|
|
1432
|
+
const archivedJsonl = jsonlPathForSessionId(deps.spawnCwd, row.sessionId, { archived: true });
|
|
1433
|
+
const jsonlPath = existsSync(topJsonl) ? topJsonl : archivedJsonl;
|
|
1434
|
+
if (!existsSync(jsonlPath)) {
|
|
1435
|
+
timed(deps.logger, 'GET', `/${id}/metering`, 404, Date.now() - start);
|
|
1436
|
+
return c.json({ error: 'session-not-found' }, 404);
|
|
1437
|
+
}
|
|
1438
|
+
const summary = await computeMetering(jsonlPath, { logger: deps.logger });
|
|
1439
|
+
const checksum = createHash('sha256').update(JSON.stringify(summary)).digest('hex').slice(0, 16);
|
|
1440
|
+
const bytes = statSync(jsonlPath).size;
|
|
1441
|
+
deps.logger(`[metering] op=surface caller=http sessionId=${row.sessionId.slice(0, 8)} checksum=${checksum}`);
|
|
1442
|
+
deps.logger(`[metering] op=http sessionId=${row.sessionId.slice(0, 8)} ms=${Date.now() - start} bytes=${bytes}`);
|
|
1443
|
+
timed(deps.logger, 'GET', `/${id}/metering`, 200, Date.now() - start);
|
|
1444
|
+
return c.json(summary, 200);
|
|
1445
|
+
});
|
|
1405
1446
|
app.post('/:sessionId/archive', async (c) => {
|
|
1406
1447
|
const start = Date.now();
|
|
1407
1448
|
const id = c.req.param('sessionId');
|
|
@@ -2394,6 +2435,28 @@ export function buildHttpApp(deps) {
|
|
|
2394
2435
|
// ingest, public, specialist, channel cold-start) on the settings defaults
|
|
2395
2436
|
// even if a future caller were to put model/effort on its body.
|
|
2396
2437
|
const freshAdminLevers = mode === 'fresh' && rcRole === 'admin';
|
|
2438
|
+
// Task 1392 — resolve whether this spawn runs under the WhatsApp Sonnet-5/max
|
|
2439
|
+
// override, for BOTH the argv and the reported launch params below. Only
|
|
2440
|
+
// sessions BORN under the override adopt it, so an existing Opus-born WhatsApp
|
|
2441
|
+
// session finishes its life on Opus:
|
|
2442
|
+
// - fresh: a WhatsApp admin spawn (gateway body carries role:'admin',
|
|
2443
|
+
// channel:'whatsapp', and waChannel) is birthed under the override. The
|
|
2444
|
+
// channel gate matches exactly what the classification sidecar records
|
|
2445
|
+
// (`classifyChannel`), so the argv override and the born-stamp can never
|
|
2446
|
+
// disagree.
|
|
2447
|
+
// - resume: the override is inherited iff the session's classification
|
|
2448
|
+
// sidecar was stamped model=SONNET_MODEL at birth. A bare operator/PIN
|
|
2449
|
+
// resume omits role/channel/waChannel, so the sidecar — not the request
|
|
2450
|
+
// body — is the authoritative born-under-override signal (no other spawn
|
|
2451
|
+
// path stamps a WhatsApp-admin sidecar with a Sonnet model).
|
|
2452
|
+
const whatsappResumeSidecar = mode === 'resume' && sessionId
|
|
2453
|
+
? readSidecar(sidecarPathForSessionId(effectiveAccountDir, sessionId), deps.logger).sidecar
|
|
2454
|
+
: null;
|
|
2455
|
+
const whatsappSonnetSpawn = mode === 'fresh'
|
|
2456
|
+
? rcRole === 'admin' && adminChannel === 'whatsapp' && waChannel !== undefined
|
|
2457
|
+
: whatsappResumeSidecar?.role === 'admin' &&
|
|
2458
|
+
whatsappResumeSidecar?.channel === 'whatsapp' &&
|
|
2459
|
+
whatsappResumeSidecar?.model === WHATSAPP_ADMIN_MODEL;
|
|
2397
2460
|
const argv = ['--remote-control'];
|
|
2398
2461
|
// Task 945 — `name` is the row's display label, never a prompt. It must NOT
|
|
2399
2462
|
// be pushed as a positional: the CLI treats a bare positional as the initial
|
|
@@ -2419,11 +2482,16 @@ export function buildHttpApp(deps) {
|
|
|
2419
2482
|
}
|
|
2420
2483
|
else if (sessionId) {
|
|
2421
2484
|
argv.push(mode === 'resume' ? '--resume' : '--session-id', sessionId);
|
|
2422
|
-
// Task
|
|
2423
|
-
//
|
|
2424
|
-
// the
|
|
2485
|
+
// Task 1392 — a WhatsApp admin session (fresh spawn or a resume born under
|
|
2486
|
+
// the override) is pinned to Sonnet 5 on both branches, so the model holds
|
|
2487
|
+
// for the session's whole life and cannot revert to the settings default.
|
|
2488
|
+
// Task 969 — otherwise, a fresh new-session spawn (the /chat new-session
|
|
2489
|
+
// popover) carries the picked model as the canonical --model flag. A resume
|
|
2490
|
+
// keeps the model its JSONL already ran under, and an absent/invalid model
|
|
2425
2491
|
// (reseatModel null) leaves the settings.json default model in force.
|
|
2426
|
-
if (
|
|
2492
|
+
if (whatsappSonnetSpawn)
|
|
2493
|
+
argv.push('--model', WHATSAPP_ADMIN_MODEL);
|
|
2494
|
+
else if (freshAdminLevers && reseatModel)
|
|
2427
2495
|
argv.push('--model', reseatModel);
|
|
2428
2496
|
}
|
|
2429
2497
|
// Task 592 — per-spawn bypass-permissions waiver. The brand settings.json
|
|
@@ -2445,6 +2513,14 @@ export function buildHttpApp(deps) {
|
|
|
2445
2513
|
if (reseatEffort)
|
|
2446
2514
|
inlineSettings.effortLevel = reseatEffort;
|
|
2447
2515
|
}
|
|
2516
|
+
else if (whatsappSonnetSpawn) {
|
|
2517
|
+
// Task 1392 — WhatsApp admin effort is pinned to `max` on both the fresh
|
|
2518
|
+
// spawn and every resume born under the override. `max` is session-only
|
|
2519
|
+
// (invalid as a settings.json effortLevel), so it rides the --effort argv
|
|
2520
|
+
// flag; asserting it on resume too stops the effort reverting to the
|
|
2521
|
+
// settings default (medium) on the session's second turn.
|
|
2522
|
+
argv.push('--effort', WHATSAPP_ADMIN_EFFORT);
|
|
2523
|
+
}
|
|
2448
2524
|
else if (freshAdminLevers && freshEffort) {
|
|
2449
2525
|
if (freshEffort === 'max')
|
|
2450
2526
|
argv.push('--effort', 'max');
|
|
@@ -2731,11 +2807,21 @@ export function buildHttpApp(deps) {
|
|
|
2731
2807
|
// Task 969 — a fresh new-session spawn carrying picked levers runs under
|
|
2732
2808
|
// them too (not just a fork), so the sidecar + lifeline + the /chat params
|
|
2733
2809
|
// row report the model/effort the session actually launched on.
|
|
2734
|
-
const effectiveRcModel =
|
|
2810
|
+
const effectiveRcModel = whatsappSonnetSpawn
|
|
2811
|
+
? WHATSAPP_ADMIN_MODEL
|
|
2812
|
+
: (forkFromSessionId !== null || freshAdminLevers) && reseatModel
|
|
2813
|
+
? reseatModel
|
|
2814
|
+
: resolveSettingsModel(deps.claudeConfigDir);
|
|
2735
2815
|
// Task 970 — the fork path reports its 4-level effort; the fresh path reports
|
|
2736
2816
|
// its 5-level pick (incl. `max`). Falls back to the settings-resolved effort
|
|
2737
2817
|
// when neither path carries one (absent on a fork, invalid/absent on a fresh).
|
|
2738
|
-
const pickedRcEffort =
|
|
2818
|
+
const pickedRcEffort = whatsappSonnetSpawn
|
|
2819
|
+
? WHATSAPP_ADMIN_EFFORT
|
|
2820
|
+
: forkFromSessionId !== null
|
|
2821
|
+
? reseatEffort
|
|
2822
|
+
: freshAdminLevers
|
|
2823
|
+
? freshEffort
|
|
2824
|
+
: undefined;
|
|
2739
2825
|
const effectiveRcEffort = pickedRcEffort ?? resolveSettingsEffort(deps.claudeConfigDir);
|
|
2740
2826
|
// Step 2 — the exact claude argv (the inner command). The systemd-run
|
|
2741
2827
|
// wrap is composed by the spawnPty adapter; logging the inner argv
|
|
@@ -2859,7 +2945,11 @@ export function buildHttpApp(deps) {
|
|
|
2859
2945
|
// passes no --debug=auto-mode.
|
|
2860
2946
|
permissionMode: effectiveRcPermissionMode,
|
|
2861
2947
|
effectivePermissionMode: null,
|
|
2862
|
-
model
|
|
2948
|
+
// Task 1392 — a fresh WhatsApp admin spawn stamps its Sonnet model
|
|
2949
|
+
// here so a later resume can read this marker back and re-assert the
|
|
2950
|
+
// override; every other spawn leaves this null (the wire `model`
|
|
2951
|
+
// still derives from the JSONL, per the sidecar field contract).
|
|
2952
|
+
model: whatsappSonnetSpawn ? WHATSAPP_ADMIN_MODEL : null,
|
|
2863
2953
|
hidden: false,
|
|
2864
2954
|
specialist: null,
|
|
2865
2955
|
scopeUnitToken: unitToken,
|