@namzu/cli 28.1.0 → 29.0.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.
- package/CHANGELOG.md +92 -0
- package/dist/integrations/subagents/runtime.d.ts +25 -0
- package/dist/integrations/subagents/runtime.d.ts.map +1 -1
- package/dist/integrations/subagents/runtime.js +40 -4
- package/dist/integrations/subagents/runtime.js.map +1 -1
- package/dist/tui/AgentExplorer.d.ts +28 -4
- package/dist/tui/AgentExplorer.d.ts.map +1 -1
- package/dist/tui/AgentExplorer.js +177 -35
- package/dist/tui/AgentExplorer.js.map +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +235 -21
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/Composer.d.ts.map +1 -1
- package/dist/tui/Composer.js +10 -4
- package/dist/tui/Composer.js.map +1 -1
- package/dist/tui/ComposerFrame.d.ts +10 -1
- package/dist/tui/ComposerFrame.d.ts.map +1 -1
- package/dist/tui/ComposerFrame.js +27 -4
- package/dist/tui/ComposerFrame.js.map +1 -1
- package/dist/tui/EffortSlider.d.ts +54 -0
- package/dist/tui/EffortSlider.d.ts.map +1 -0
- package/dist/tui/EffortSlider.js +131 -0
- package/dist/tui/EffortSlider.js.map +1 -0
- package/dist/tui/LiveActivity.d.ts +23 -3
- package/dist/tui/LiveActivity.d.ts.map +1 -1
- package/dist/tui/LiveActivity.js +23 -17
- package/dist/tui/LiveActivity.js.map +1 -1
- package/dist/tui/Markdown.d.ts +29 -2
- package/dist/tui/Markdown.d.ts.map +1 -1
- package/dist/tui/Markdown.js +74 -36
- package/dist/tui/Markdown.js.map +1 -1
- package/dist/tui/StatusBar.js +1 -1
- package/dist/tui/StatusBar.js.map +1 -1
- package/dist/tui/Transcript.d.ts +24 -1
- package/dist/tui/Transcript.d.ts.map +1 -1
- package/dist/tui/Transcript.js +35 -8
- package/dist/tui/Transcript.js.map +1 -1
- package/dist/tui/ViewportBound.d.ts +48 -0
- package/dist/tui/ViewportBound.d.ts.map +1 -0
- package/dist/tui/ViewportBound.js +55 -0
- package/dist/tui/ViewportBound.js.map +1 -0
- package/dist/tui/agent-transcript-rows.d.ts +59 -0
- package/dist/tui/agent-transcript-rows.d.ts.map +1 -0
- package/dist/tui/agent-transcript-rows.js +115 -0
- package/dist/tui/agent-transcript-rows.js.map +1 -0
- package/dist/tui/agent.d.ts +39 -0
- package/dist/tui/agent.d.ts.map +1 -1
- package/dist/tui/agent.js +86 -5
- package/dist/tui/agent.js.map +1 -1
- package/dist/tui/live-window.d.ts +16 -0
- package/dist/tui/live-window.d.ts.map +1 -1
- package/dist/tui/live-window.js +50 -3
- package/dist/tui/live-window.js.map +1 -1
- package/dist/tui/markdown-block-cache.d.ts +9 -7
- package/dist/tui/markdown-block-cache.d.ts.map +1 -1
- package/dist/tui/markdown-block-cache.js +9 -7
- package/dist/tui/markdown-block-cache.js.map +1 -1
- package/dist/tui/markdown-table.d.ts +55 -0
- package/dist/tui/markdown-table.d.ts.map +1 -0
- package/dist/tui/markdown-table.js +175 -0
- package/dist/tui/markdown-table.js.map +1 -0
- package/dist/tui/markdown-wrap.d.ts +53 -0
- package/dist/tui/markdown-wrap.d.ts.map +1 -0
- package/dist/tui/markdown-wrap.js +189 -0
- package/dist/tui/markdown-wrap.js.map +1 -0
- package/dist/tui/markdownParser.d.ts +6 -0
- package/dist/tui/markdownParser.d.ts.map +1 -1
- package/dist/tui/markdownParser.js +49 -10
- package/dist/tui/markdownParser.js.map +1 -1
- package/dist/tui/slashCommands.d.ts.map +1 -1
- package/dist/tui/slashCommands.js +3 -0
- package/dist/tui/slashCommands.js.map +1 -1
- package/dist/tui/stream-blocks.d.ts.map +1 -1
- package/dist/tui/stream-blocks.js +32 -3
- package/dist/tui/stream-blocks.js.map +1 -1
- package/dist/tui/theme.d.ts +13 -0
- package/dist/tui/theme.d.ts.map +1 -1
- package/dist/tui/theme.js +16 -0
- package/dist/tui/theme.js.map +1 -1
- package/dist/tui/types.d.ts +7 -2
- package/dist/tui/types.d.ts.map +1 -1
- package/dist/tui/units.d.ts +6 -0
- package/dist/tui/units.d.ts.map +1 -0
- package/dist/tui/units.js +20 -0
- package/dist/tui/units.js.map +1 -0
- package/dist/tui/web-activity.d.ts +58 -0
- package/dist/tui/web-activity.d.ts.map +1 -0
- package/dist/tui/web-activity.js +105 -0
- package/dist/tui/web-activity.js.map +1 -0
- package/package.json +8 -8
package/dist/tui/agent.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createCurrentCredentialReader } from '../integrations/providers/current-credential.js';
|
|
2
2
|
import { createWebSearchTool, resolveWebSearch, webSearchLabel, } from '../integrations/web/search.js';
|
|
3
|
+
import { countListedResults, webActivityFromInput, webActivityKind, webCallTitle, } from './web-activity.js';
|
|
3
4
|
/**
|
|
4
5
|
* TUI agent session — provider-direct, tool-enabled.
|
|
5
6
|
*
|
|
@@ -1021,6 +1022,10 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
1021
1022
|
// Agent tool. Keying the review channel by the executing turn keeps two
|
|
1022
1023
|
// concurrent sends from borrowing each other's prompt or approval latch.
|
|
1023
1024
|
const delegatedResumeHandlers = new Map();
|
|
1025
|
+
// Beside each borrowed handler, the switch that sends it the batches it
|
|
1026
|
+
// would otherwise never see (`reviewAllowedCalls`): without it a child's
|
|
1027
|
+
// rule-allowed or already-approved call ran past a handler in plan mode.
|
|
1028
|
+
const delegatedReviewAllowedCalls = new Map();
|
|
1024
1029
|
const goalToolNames = new Set(SESSION_GOAL_TOOL_NAMES);
|
|
1025
1030
|
if (options.sessionGoals) {
|
|
1026
1031
|
registry.register(buildSessionGoalTools(options.sessionGoals, (turnId) => goalAuthorities.get(turnId)));
|
|
@@ -1211,6 +1216,7 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
1211
1216
|
},
|
|
1212
1217
|
sandboxWorkspace,
|
|
1213
1218
|
resolveResumeHandler: (turnId) => delegatedResumeHandlers.get(turnId),
|
|
1219
|
+
resolveReviewAllowedCalls: (turnId) => delegatedReviewAllowedCalls.get(turnId),
|
|
1214
1220
|
resolveWaitForInbound: (turnId) => delegatedInputWaiters.get(turnId),
|
|
1215
1221
|
...(sandbox.provider ? { sandboxProvider: sandbox.provider } : {}),
|
|
1216
1222
|
...(options.sandbox?.teardownTimeoutMs !== undefined
|
|
@@ -1647,7 +1653,7 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
1647
1653
|
* checkpoint cannot carry. `resumeDurable` and `resumePaused` differ only
|
|
1648
1654
|
* in where the log and its lease come from.
|
|
1649
1655
|
*/
|
|
1650
|
-
const kernelResume = ({ entry, sessionLog, checkpointStore, lease, signal, checkpointId, listener, }) => operations.promise(signal, async (ownedSignal) => {
|
|
1656
|
+
const kernelResume = ({ entry, sessionLog, checkpointStore, lease, signal, checkpointId, listener, permissionMode, currentPermissionMode, }) => operations.promise(signal, async (ownedSignal) => {
|
|
1651
1657
|
const selectTaskStore = beginTaskStoreReadout();
|
|
1652
1658
|
// The turn's own limits, as its `turn_started` recorded them.
|
|
1653
1659
|
const resumedLimits = (await readStoredTurnGuards(sessionLog, entry.turnId)) ?? resolveTurnGuards(options.limits);
|
|
@@ -1684,12 +1690,32 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
1684
1690
|
]
|
|
1685
1691
|
.filter((s) => Boolean(s))
|
|
1686
1692
|
.join('\n\n') || undefined;
|
|
1687
|
-
const resumeHandler = makeResumeHandler(approval, undefined, options.permissionMode, (name, input) => isPromptExempt(registry, name, input), { unattendedSandboxEscape });
|
|
1688
1693
|
if (delegatedResumeHandlers.has(entry.turnId)) {
|
|
1689
1694
|
throw new Error(`Turn ${entry.turnId} already owns a delegated review channel.`);
|
|
1690
1695
|
}
|
|
1696
|
+
// The resumed turn is decided under the caller's mode, else the
|
|
1697
|
+
// session's, read at every decision exactly as a new turn's is: the
|
|
1698
|
+
// interactive terminal creates its session without a mode and hands
|
|
1699
|
+
// one to each turn, so the session's alone left a TUI `/resume` in
|
|
1700
|
+
// plan mode under `auto`. Plan is stricter than the rules, so while it
|
|
1701
|
+
// holds a batch a rule allows, or an approval earlier in the turn
|
|
1702
|
+
// covers, still reaches the handler that refuses it — in this turn and
|
|
1703
|
+
// in every turn it delegates. No prompt stands behind the handler:
|
|
1704
|
+
// nobody answers a drainer's terminal, and `/resume` never asked.
|
|
1705
|
+
const modeControl = createLiveModeControl({
|
|
1706
|
+
initial: permissionMode ?? options.permissionMode ?? 'auto',
|
|
1707
|
+
...(currentPermissionMode ? { read: currentPermissionMode } : {}),
|
|
1708
|
+
...(recordedModes.has(String(entry.sessionId))
|
|
1709
|
+
? { recorded: recordedModes.get(String(entry.sessionId)) }
|
|
1710
|
+
: {}),
|
|
1711
|
+
handlerFor: (mode) => makeResumeHandler(approval, undefined, mode, reviewExemptionFor(mode, registry, (input) => subagentRuntime?.launchesReadOnlyAgent(input) === true), { unattendedSandboxEscape }),
|
|
1712
|
+
});
|
|
1713
|
+
const resumeHandler = modeControl.handler;
|
|
1714
|
+
const reviewAllowedCalls = modeControl.reviewAllowedCalls;
|
|
1715
|
+
liveModeControls.add(modeControl);
|
|
1691
1716
|
const turnScope = { ...entry, topicId: scope.topicId };
|
|
1692
1717
|
delegatedResumeHandlers.set(entry.turnId, resumeHandler);
|
|
1718
|
+
delegatedReviewAllowedCalls.set(entry.turnId, reviewAllowedCalls);
|
|
1693
1719
|
delegationScopes.set(entry.turnId, turnScope);
|
|
1694
1720
|
delegationLimits.set(entry.turnId, resumedLimits);
|
|
1695
1721
|
const turnTaskStore = selectTaskStore(turnScope);
|
|
@@ -1762,6 +1788,9 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
1762
1788
|
// prompt would block the pass forever on a turn nobody is watching.
|
|
1763
1789
|
// The gate's deny rules still apply.
|
|
1764
1790
|
resumeHandler,
|
|
1791
|
+
approvalPolicyName: modeControl.initialName,
|
|
1792
|
+
onApprovalPolicy: (box) => modeControl.attach(box),
|
|
1793
|
+
reviewAllowedCalls,
|
|
1765
1794
|
signal: ownedSignal,
|
|
1766
1795
|
// Attribution comes from the ENTRY, not from this session: the turn
|
|
1767
1796
|
// belongs to whoever started it, and stamping the drainer's ids onto
|
|
@@ -1797,8 +1826,11 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
1797
1826
|
});
|
|
1798
1827
|
}
|
|
1799
1828
|
finally {
|
|
1829
|
+
liveModeControls.delete(modeControl);
|
|
1830
|
+
recordedModes.set(String(entry.sessionId), modeControl.current());
|
|
1800
1831
|
if (delegatedResumeHandlers.get(entry.turnId) === resumeHandler) {
|
|
1801
1832
|
delegatedResumeHandlers.delete(entry.turnId);
|
|
1833
|
+
delegatedReviewAllowedCalls.delete(entry.turnId);
|
|
1802
1834
|
delegationScopes.delete(entry.turnId);
|
|
1803
1835
|
delegationLimits.delete(entry.turnId);
|
|
1804
1836
|
await subagentRuntime?.releaseTurn(entry.turnId);
|
|
@@ -1811,7 +1843,7 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
1811
1843
|
* headless caller renders a resumed turn exactly as it rendered the first
|
|
1812
1844
|
* segment.
|
|
1813
1845
|
*/
|
|
1814
|
-
const resumePausedStream = ({ turnId, checkpointId, signal, }) => {
|
|
1846
|
+
const resumePausedStream = ({ turnId, checkpointId, signal, permissionMode, currentPermissionMode, }) => {
|
|
1815
1847
|
const queue = [];
|
|
1816
1848
|
let wake;
|
|
1817
1849
|
let settled = false;
|
|
@@ -1829,6 +1861,8 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
1829
1861
|
sessionLog,
|
|
1830
1862
|
...(signal ? { signal } : {}),
|
|
1831
1863
|
...(checkpointId !== undefined ? { checkpointId: checkpointId } : {}),
|
|
1864
|
+
...(permissionMode ? { permissionMode } : {}),
|
|
1865
|
+
...(currentPermissionMode ? { currentPermissionMode } : {}),
|
|
1832
1866
|
listener: (event) => {
|
|
1833
1867
|
queue.push(event);
|
|
1834
1868
|
wake?.();
|
|
@@ -2023,7 +2057,7 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
2023
2057
|
...(recordedModes.has(String(turnScope.sessionId))
|
|
2024
2058
|
? { recorded: recordedModes.get(String(turnScope.sessionId)) }
|
|
2025
2059
|
: {}),
|
|
2026
|
-
handlerFor: (mode) => makeResumeHandler(approval, opts?.onPermission, mode, (
|
|
2060
|
+
handlerFor: (mode) => makeResumeHandler(approval, opts?.onPermission, mode, reviewExemptionFor(mode, runTools, (input) => subagentRuntime?.launchesReadOnlyAgent(input) === true), { unattendedSandboxEscape }),
|
|
2027
2061
|
});
|
|
2028
2062
|
const resumeHandler = modeControl.handler;
|
|
2029
2063
|
liveModeControls.add(modeControl);
|
|
@@ -2043,6 +2077,7 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
2043
2077
|
}
|
|
2044
2078
|
claimed.add(turnId);
|
|
2045
2079
|
delegatedResumeHandlers.set(turnId, resumeHandler);
|
|
2080
|
+
delegatedReviewAllowedCalls.set(turnId, modeControl.reviewAllowedCalls);
|
|
2046
2081
|
if (opts?.onModelSwitch)
|
|
2047
2082
|
modelSwitchHandlers.set(turnId, opts.onModelSwitch);
|
|
2048
2083
|
if (opts?.waitForInbound)
|
|
@@ -2331,6 +2366,7 @@ export async function createAgentSession(prefs, detected, options = {}) {
|
|
|
2331
2366
|
if (delegatedResumeHandlers.get(turnId) !== resumeHandler)
|
|
2332
2367
|
continue;
|
|
2333
2368
|
delegatedResumeHandlers.delete(turnId);
|
|
2369
|
+
delegatedReviewAllowedCalls.delete(turnId);
|
|
2334
2370
|
modelSwitchHandlers.delete(turnId);
|
|
2335
2371
|
delegatedInputWaiters.delete(turnId);
|
|
2336
2372
|
delegationScopes.delete(turnId);
|
|
@@ -2986,6 +3022,27 @@ export function makeResumeHandler(approval, onPermission, mode = onPermission ?
|
|
|
2986
3022
|
* registry does not know.
|
|
2987
3023
|
*/
|
|
2988
3024
|
export const isPromptExempt = isReviewExempt;
|
|
3025
|
+
/** The delegation tool whose read-only launches {@link reviewExemptionFor} lets through. */
|
|
3026
|
+
export const AGENT_LAUNCH_TOOL = 'Agent';
|
|
3027
|
+
/**
|
|
3028
|
+
* What skips review under `mode`: the kernel's exemption, and — in every mode
|
|
3029
|
+
* but `strict` — an `Agent` call that starts a read-only child on the
|
|
3030
|
+
* session's own provider and model (`launchesReadOnlyAgent`).
|
|
3031
|
+
*
|
|
3032
|
+
* Starting such a child changes nothing by itself: its roster holds no tool
|
|
3033
|
+
* that writes, and every call it makes is reviewed under this same mode as
|
|
3034
|
+
* before. What the operator stops being asked is "may I start a reader?".
|
|
3035
|
+
* A launch that is not read-only, or that picks another provider, model or
|
|
3036
|
+
* effort, is asked about as before. `strict` still refuses it, since no rule
|
|
3037
|
+
* allowed it; `plan` lets it start, since reading is what plan mode is for.
|
|
3038
|
+
* An operator who wants every launch asked about writes
|
|
3039
|
+
* `permissions: { Agent: "ask" }`: an `ask` rule is an explicit review, which
|
|
3040
|
+
* no exemption skips.
|
|
3041
|
+
*/
|
|
3042
|
+
export function reviewExemptionFor(mode, registry, launchesReadOnlyAgent) {
|
|
3043
|
+
return (name, input) => isPromptExempt(registry, name, input) ||
|
|
3044
|
+
(mode !== 'strict' && name === AGENT_LAUNCH_TOOL && launchesReadOnlyAgent(input));
|
|
3045
|
+
}
|
|
2989
3046
|
/** The exempt roster, sorted, for the surface that has to NAME it. */
|
|
2990
3047
|
export function promptExemptToolNames(registry) {
|
|
2991
3048
|
return registry
|
|
@@ -3009,12 +3066,23 @@ export function toAgentEvent(event, presenter) {
|
|
|
3009
3066
|
toolUseId: event.tool.id,
|
|
3010
3067
|
toolName: 'web_search',
|
|
3011
3068
|
};
|
|
3069
|
+
// A page action names an address rather than a query, and reads as
|
|
3070
|
+
// a fetch; everything else is a search, named once the provider says.
|
|
3071
|
+
const web = event.tool.url && !event.tool.query
|
|
3072
|
+
? { kind: 'fetch', target: event.tool.url, hosted: true }
|
|
3073
|
+
: {
|
|
3074
|
+
kind: 'search',
|
|
3075
|
+
hosted: true,
|
|
3076
|
+
...(event.tool.query ? { target: event.tool.query } : {}),
|
|
3077
|
+
...(event.tool.results !== undefined ? { results: event.tool.results } : {}),
|
|
3078
|
+
};
|
|
3012
3079
|
return event.tool.status === 'running'
|
|
3013
3080
|
? {
|
|
3014
3081
|
...common,
|
|
3015
3082
|
kind: 'tool-start',
|
|
3016
|
-
summary:
|
|
3083
|
+
summary: webCallTitle(web),
|
|
3017
3084
|
standalone: true,
|
|
3085
|
+
web,
|
|
3018
3086
|
}
|
|
3019
3087
|
: {
|
|
3020
3088
|
...common,
|
|
@@ -3022,6 +3090,7 @@ export function toAgentEvent(event, presenter) {
|
|
|
3022
3090
|
summary: event.tool.status === 'completed' ? '' : 'Provider-hosted search failed',
|
|
3023
3091
|
isError: event.tool.status !== 'completed',
|
|
3024
3092
|
output: event.tool.status,
|
|
3093
|
+
web,
|
|
3025
3094
|
};
|
|
3026
3095
|
}
|
|
3027
3096
|
case 'text_delta':
|
|
@@ -3061,6 +3130,10 @@ export function toAgentEvent(event, presenter) {
|
|
|
3061
3130
|
: {}),
|
|
3062
3131
|
};
|
|
3063
3132
|
})(),
|
|
3133
|
+
...(() => {
|
|
3134
|
+
const web = webActivityFromInput(event.toolName, event.input);
|
|
3135
|
+
return web ? { web } : {};
|
|
3136
|
+
})(),
|
|
3064
3137
|
};
|
|
3065
3138
|
case 'tool_progress':
|
|
3066
3139
|
return {
|
|
@@ -3098,6 +3171,13 @@ export function toAgentEvent(event, presenter) {
|
|
|
3098
3171
|
...(withoutRepeatedSummary && withoutRepeatedSummary.length > 0
|
|
3099
3172
|
? { detail: withoutRepeatedSummary }
|
|
3100
3173
|
: {}),
|
|
3174
|
+
...(() => {
|
|
3175
|
+
const kind = webActivityKind(event.toolName);
|
|
3176
|
+
if (!kind)
|
|
3177
|
+
return {};
|
|
3178
|
+
const results = kind === 'search' && !event.isError ? countListedResults(event.result) : undefined;
|
|
3179
|
+
return { web: { kind, ...(results !== undefined ? { results } : {}) } };
|
|
3180
|
+
})(),
|
|
3101
3181
|
};
|
|
3102
3182
|
}
|
|
3103
3183
|
case 'token_usage_updated':
|
|
@@ -3113,6 +3193,7 @@ export function toAgentEvent(event, presenter) {
|
|
|
3113
3193
|
sessionId: event.sessionId,
|
|
3114
3194
|
...(event.turnId ? { turnId: event.turnId } : {}),
|
|
3115
3195
|
totalTokens: event.usage.totalTokens,
|
|
3196
|
+
outputTokens: event.usage.completionTokens,
|
|
3116
3197
|
...(event.budget ? { budget: event.budget } : {}),
|
|
3117
3198
|
cost: event.cost,
|
|
3118
3199
|
...(event.contextTokens !== undefined ? { contextTokens: event.contextTokens } : {}),
|