@poncho-ai/cli 0.19.1 → 0.20.1
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/.turbo/turbo-build.log +4 -4
- package/CHANGELOG.md +17 -0
- package/dist/{chunk-7P53QSP5.js → chunk-J4OZUXG5.js} +58 -17
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/dist/{run-interactive-ink-4KVVPMR3.js → run-interactive-ink-S3D42QQY.js} +1 -1
- package/package.json +4 -4
- package/src/index.ts +32 -16
- package/src/web-ui-client.ts +25 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @poncho-ai/cli@0.
|
|
2
|
+
> @poncho-ai/cli@0.20.1 build /home/runner/work/poncho-ai/poncho-ai/packages/cli
|
|
3
3
|
> tsup src/index.ts src/cli.ts --format esm --dts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/cli.ts, src/index.ts
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
[34mCLI[39m Target: es2022
|
|
9
9
|
[34mESM[39m Build start
|
|
10
10
|
[32mESM[39m [1mdist/cli.js [22m[32m94.00 B[39m
|
|
11
|
-
[32mESM[39m [1mdist/run-interactive-ink-
|
|
12
|
-
[32mESM[39m [1mdist/chunk-
|
|
11
|
+
[32mESM[39m [1mdist/run-interactive-ink-S3D42QQY.js [22m[32m55.30 KB[39m
|
|
12
|
+
[32mESM[39m [1mdist/chunk-J4OZUXG5.js [22m[32m383.23 KB[39m
|
|
13
13
|
[32mESM[39m [1mdist/index.js [22m[32m857.00 B[39m
|
|
14
14
|
[32mESM[39m ⚡️ Build success in 60ms
|
|
15
15
|
[34mDTS[39m Build start
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 3870ms
|
|
17
17
|
[32mDTS[39m [1mdist/cli.d.ts [22m[32m20.00 B[39m
|
|
18
18
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m3.59 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @poncho-ai/cli
|
|
2
2
|
|
|
3
|
+
## 0.20.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`a9563b0`](https://github.com/cesr/poncho-ai/commit/a9563b03dfbdb6eb8cc9536be72b2bfd76c042ef) Thanks [@cesr](https://github.com/cesr)! - Fix approval resume dying on Vercel: wrap the post-approval tool execution and run resumption in waitUntil so the serverless function stays alive until the work completes.
|
|
8
|
+
|
|
9
|
+
## 0.20.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [`5df6b5f`](https://github.com/cesr/poncho-ai/commit/5df6b5fcdc98e0445bea504dc9d077f02d1e954f) Thanks [@cesr](https://github.com/cesr)! - Add polling fallback for web UI on serverless deployments: when the SSE event stream is unavailable (different instance from the webhook handler), the UI polls the conversation every 2 seconds until the run completes. Conversations now track a persisted `runStatus` field.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- Updated dependencies [[`5df6b5f`](https://github.com/cesr/poncho-ai/commit/5df6b5fcdc98e0445bea504dc9d077f02d1e954f)]:
|
|
18
|
+
- @poncho-ai/harness@0.20.0
|
|
19
|
+
|
|
3
20
|
## 0.19.1
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -2493,8 +2493,7 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2493
2493
|
setStreaming(true);
|
|
2494
2494
|
streamConversationEvents(conversationId, { liveOnly: true }).finally(() => {
|
|
2495
2495
|
if (state.activeConversationId === conversationId) {
|
|
2496
|
-
|
|
2497
|
-
renderMessages(state.activeMessages, false);
|
|
2496
|
+
pollUntilRunIdle(conversationId);
|
|
2498
2497
|
}
|
|
2499
2498
|
});
|
|
2500
2499
|
}
|
|
@@ -2561,6 +2560,30 @@ var getWebUiClientScript = (markedSource2) => `
|
|
|
2561
2560
|
});
|
|
2562
2561
|
};
|
|
2563
2562
|
|
|
2563
|
+
const pollUntilRunIdle = (conversationId) => {
|
|
2564
|
+
const poll = async () => {
|
|
2565
|
+
if (state.activeConversationId !== conversationId) return;
|
|
2566
|
+
try {
|
|
2567
|
+
var payload = await api("/api/conversations/" + encodeURIComponent(conversationId));
|
|
2568
|
+
if (state.activeConversationId !== conversationId) return;
|
|
2569
|
+
if (payload.conversation) {
|
|
2570
|
+
state.activeMessages = payload.conversation.messages || [];
|
|
2571
|
+
renderMessages(state.activeMessages, payload.hasActiveRun);
|
|
2572
|
+
}
|
|
2573
|
+
if (payload.hasActiveRun) {
|
|
2574
|
+
setTimeout(poll, 2000);
|
|
2575
|
+
} else {
|
|
2576
|
+
setStreaming(false);
|
|
2577
|
+
renderMessages(state.activeMessages, false);
|
|
2578
|
+
}
|
|
2579
|
+
} catch {
|
|
2580
|
+
setStreaming(false);
|
|
2581
|
+
renderMessages(state.activeMessages, false);
|
|
2582
|
+
}
|
|
2583
|
+
};
|
|
2584
|
+
setTimeout(poll, 1500);
|
|
2585
|
+
};
|
|
2586
|
+
|
|
2564
2587
|
const streamConversationEvents = (conversationId, options) => {
|
|
2565
2588
|
const liveOnly = options && options.liveOnly;
|
|
2566
2589
|
return new Promise((resolve) => {
|
|
@@ -7867,11 +7890,19 @@ var createRequestHandler = async (options) => {
|
|
|
7867
7890
|
}
|
|
7868
7891
|
conv.runtimeRunId = latestRunId || conv.runtimeRunId;
|
|
7869
7892
|
conv.pendingApprovals = [];
|
|
7893
|
+
conv.runStatus = "idle";
|
|
7870
7894
|
if (runContextTokens > 0) conv.contextTokens = runContextTokens;
|
|
7871
7895
|
if (runContextWindow > 0) conv.contextWindow = runContextWindow;
|
|
7872
7896
|
conv.updatedAt = Date.now();
|
|
7873
7897
|
await conversationStore.update(conv);
|
|
7874
7898
|
}
|
|
7899
|
+
} else {
|
|
7900
|
+
const conv = await conversationStore.get(conversationId);
|
|
7901
|
+
if (conv) {
|
|
7902
|
+
conv.runStatus = "idle";
|
|
7903
|
+
conv.updatedAt = Date.now();
|
|
7904
|
+
await conversationStore.update(conv);
|
|
7905
|
+
}
|
|
7875
7906
|
}
|
|
7876
7907
|
finishConversationStream(conversationId);
|
|
7877
7908
|
activeConversationRuns.delete(conversationId);
|
|
@@ -7922,6 +7953,7 @@ var createRequestHandler = async (options) => {
|
|
|
7922
7953
|
};
|
|
7923
7954
|
await updateConversation((c) => {
|
|
7924
7955
|
c.messages = [...historyMessages, { role: "user", content: userContent }];
|
|
7956
|
+
c.runStatus = "running";
|
|
7925
7957
|
});
|
|
7926
7958
|
let latestRunId = "";
|
|
7927
7959
|
let assistantResponse = "";
|
|
@@ -8072,9 +8104,14 @@ var createRequestHandler = async (options) => {
|
|
|
8072
8104
|
c.messages = buildMessages();
|
|
8073
8105
|
c.runtimeRunId = latestRunId || c.runtimeRunId;
|
|
8074
8106
|
c.pendingApprovals = [];
|
|
8107
|
+
c.runStatus = "idle";
|
|
8075
8108
|
if (runContextTokens > 0) c.contextTokens = runContextTokens;
|
|
8076
8109
|
if (runContextWindow > 0) c.contextWindow = runContextWindow;
|
|
8077
8110
|
});
|
|
8111
|
+
} else {
|
|
8112
|
+
await updateConversation((c) => {
|
|
8113
|
+
c.runStatus = "idle";
|
|
8114
|
+
});
|
|
8078
8115
|
}
|
|
8079
8116
|
finishConversationStream(conversationId);
|
|
8080
8117
|
if (latestRunId) {
|
|
@@ -8086,20 +8123,20 @@ var createRequestHandler = async (options) => {
|
|
|
8086
8123
|
return { response };
|
|
8087
8124
|
}
|
|
8088
8125
|
};
|
|
8126
|
+
let waitUntilHook;
|
|
8127
|
+
if (process.env.VERCEL) {
|
|
8128
|
+
try {
|
|
8129
|
+
const modName = "@vercel/functions";
|
|
8130
|
+
const mod = await import(
|
|
8131
|
+
/* webpackIgnore: true */
|
|
8132
|
+
modName
|
|
8133
|
+
);
|
|
8134
|
+
waitUntilHook = mod.waitUntil;
|
|
8135
|
+
} catch {
|
|
8136
|
+
}
|
|
8137
|
+
}
|
|
8089
8138
|
const messagingBridges = [];
|
|
8090
8139
|
if (config?.messaging && config.messaging.length > 0) {
|
|
8091
|
-
let waitUntilHook;
|
|
8092
|
-
if (process.env.VERCEL) {
|
|
8093
|
-
try {
|
|
8094
|
-
const modName = "@vercel/functions";
|
|
8095
|
-
const mod = await import(
|
|
8096
|
-
/* webpackIgnore: true */
|
|
8097
|
-
modName
|
|
8098
|
-
);
|
|
8099
|
-
waitUntilHook = mod.waitUntil;
|
|
8100
|
-
} catch {
|
|
8101
|
-
}
|
|
8102
|
-
}
|
|
8103
8140
|
for (const channelConfig of config.messaging) {
|
|
8104
8141
|
if (channelConfig.platform === "slack") {
|
|
8105
8142
|
const adapter = new SlackAdapter({
|
|
@@ -8549,9 +8586,10 @@ data: ${JSON.stringify(data)}
|
|
|
8549
8586
|
return;
|
|
8550
8587
|
}
|
|
8551
8588
|
foundConversation.pendingApprovals = [];
|
|
8589
|
+
foundConversation.runStatus = "running";
|
|
8552
8590
|
await conversationStore.update(foundConversation);
|
|
8553
8591
|
const checkpointRef = allApprovals[0];
|
|
8554
|
-
|
|
8592
|
+
const resumeWork = (async () => {
|
|
8555
8593
|
const toolContext = {
|
|
8556
8594
|
runId: checkpointRef.runId,
|
|
8557
8595
|
agentId: identity.id,
|
|
@@ -8592,6 +8630,9 @@ data: ${JSON.stringify(data)}
|
|
|
8592
8630
|
toolResults
|
|
8593
8631
|
);
|
|
8594
8632
|
})();
|
|
8633
|
+
if (waitUntilHook) {
|
|
8634
|
+
waitUntilHook(resumeWork);
|
|
8635
|
+
}
|
|
8595
8636
|
writeJson(response, 200, { ok: true, approvalId, approved, batchComplete: true });
|
|
8596
8637
|
return;
|
|
8597
8638
|
}
|
|
@@ -8697,7 +8738,7 @@ data: ${JSON.stringify(data)}
|
|
|
8697
8738
|
}
|
|
8698
8739
|
}
|
|
8699
8740
|
const activeStream = conversationEventStreams.get(conversationId);
|
|
8700
|
-
const hasActiveRun = !!activeStream && !activeStream.finished;
|
|
8741
|
+
const hasActiveRun = !!activeStream && !activeStream.finished || conversation.runStatus === "running";
|
|
8701
8742
|
writeJson(response, 200, {
|
|
8702
8743
|
conversation: {
|
|
8703
8744
|
...conversation,
|
|
@@ -9620,7 +9661,7 @@ var runInteractive = async (workingDir, params) => {
|
|
|
9620
9661
|
await harness.initialize();
|
|
9621
9662
|
const identity = await ensureAgentIdentity2(workingDir);
|
|
9622
9663
|
try {
|
|
9623
|
-
const { runInteractiveInk } = await import("./run-interactive-ink-
|
|
9664
|
+
const { runInteractiveInk } = await import("./run-interactive-ink-S3D42QQY.js");
|
|
9624
9665
|
await runInteractiveInk({
|
|
9625
9666
|
harness,
|
|
9626
9667
|
params,
|
package/dist/cli.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@poncho-ai/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.1",
|
|
4
4
|
"description": "CLI for building and deploying AI agents",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"react": "^19.2.4",
|
|
28
28
|
"react-devtools-core": "^6.1.5",
|
|
29
29
|
"yaml": "^2.8.1",
|
|
30
|
-
"@poncho-ai/harness": "0.
|
|
31
|
-
"@poncho-ai/
|
|
32
|
-
"@poncho-ai/
|
|
30
|
+
"@poncho-ai/harness": "0.20.0",
|
|
31
|
+
"@poncho-ai/messaging": "0.2.7",
|
|
32
|
+
"@poncho-ai/sdk": "1.4.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@types/busboy": "^1.5.4",
|
package/src/index.ts
CHANGED
|
@@ -2081,11 +2081,19 @@ export const createRequestHandler = async (options?: {
|
|
|
2081
2081
|
}
|
|
2082
2082
|
conv.runtimeRunId = latestRunId || conv.runtimeRunId;
|
|
2083
2083
|
conv.pendingApprovals = [];
|
|
2084
|
+
conv.runStatus = "idle";
|
|
2084
2085
|
if (runContextTokens > 0) conv.contextTokens = runContextTokens;
|
|
2085
2086
|
if (runContextWindow > 0) conv.contextWindow = runContextWindow;
|
|
2086
2087
|
conv.updatedAt = Date.now();
|
|
2087
2088
|
await conversationStore.update(conv);
|
|
2088
2089
|
}
|
|
2090
|
+
} else {
|
|
2091
|
+
const conv = await conversationStore.get(conversationId);
|
|
2092
|
+
if (conv) {
|
|
2093
|
+
conv.runStatus = "idle";
|
|
2094
|
+
conv.updatedAt = Date.now();
|
|
2095
|
+
await conversationStore.update(conv);
|
|
2096
|
+
}
|
|
2089
2097
|
}
|
|
2090
2098
|
|
|
2091
2099
|
finishConversationStream(conversationId);
|
|
@@ -2148,9 +2156,10 @@ export const createRequestHandler = async (options?: {
|
|
|
2148
2156
|
await conversationStore.update(fresh);
|
|
2149
2157
|
};
|
|
2150
2158
|
|
|
2151
|
-
// Persist user turn
|
|
2159
|
+
// Persist user turn and mark the run as active so the web UI can detect it.
|
|
2152
2160
|
await updateConversation((c) => {
|
|
2153
2161
|
c.messages = [...historyMessages, { role: "user" as const, content: userContent }];
|
|
2162
|
+
c.runStatus = "running";
|
|
2154
2163
|
});
|
|
2155
2164
|
|
|
2156
2165
|
let latestRunId = "";
|
|
@@ -2317,9 +2326,14 @@ export const createRequestHandler = async (options?: {
|
|
|
2317
2326
|
c.messages = buildMessages();
|
|
2318
2327
|
c.runtimeRunId = latestRunId || c.runtimeRunId;
|
|
2319
2328
|
c.pendingApprovals = [];
|
|
2329
|
+
c.runStatus = "idle";
|
|
2320
2330
|
if (runContextTokens > 0) c.contextTokens = runContextTokens;
|
|
2321
2331
|
if (runContextWindow > 0) c.contextWindow = runContextWindow;
|
|
2322
2332
|
});
|
|
2333
|
+
} else {
|
|
2334
|
+
await updateConversation((c) => {
|
|
2335
|
+
c.runStatus = "idle";
|
|
2336
|
+
});
|
|
2323
2337
|
}
|
|
2324
2338
|
finishConversationStream(conversationId);
|
|
2325
2339
|
if (latestRunId) {
|
|
@@ -2334,21 +2348,19 @@ export const createRequestHandler = async (options?: {
|
|
|
2334
2348
|
},
|
|
2335
2349
|
};
|
|
2336
2350
|
|
|
2337
|
-
|
|
2338
|
-
if (
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
const mod = await import(/* webpackIgnore: true */ modName);
|
|
2346
|
-
waitUntilHook = mod.waitUntil;
|
|
2347
|
-
} catch {
|
|
2348
|
-
// @vercel/functions not installed -- fall through to no-op.
|
|
2349
|
-
}
|
|
2351
|
+
let waitUntilHook: ((promise: Promise<unknown>) => void) | undefined;
|
|
2352
|
+
if (process.env.VERCEL) {
|
|
2353
|
+
try {
|
|
2354
|
+
const modName = "@vercel/functions";
|
|
2355
|
+
const mod = await import(/* webpackIgnore: true */ modName);
|
|
2356
|
+
waitUntilHook = mod.waitUntil;
|
|
2357
|
+
} catch {
|
|
2358
|
+
// @vercel/functions not installed -- fall through to no-op.
|
|
2350
2359
|
}
|
|
2360
|
+
}
|
|
2351
2361
|
|
|
2362
|
+
const messagingBridges: AgentBridge[] = [];
|
|
2363
|
+
if (config?.messaging && config.messaging.length > 0) {
|
|
2352
2364
|
for (const channelConfig of config.messaging) {
|
|
2353
2365
|
if (channelConfig.platform === "slack") {
|
|
2354
2366
|
const adapter = new SlackAdapter({
|
|
@@ -2890,12 +2902,13 @@ export const createRequestHandler = async (options?: {
|
|
|
2890
2902
|
|
|
2891
2903
|
// All approvals in the batch are decided — execute and resume
|
|
2892
2904
|
foundConversation.pendingApprovals = [];
|
|
2905
|
+
foundConversation.runStatus = "running";
|
|
2893
2906
|
await conversationStore.update(foundConversation);
|
|
2894
2907
|
|
|
2895
2908
|
// Use the first approval as the checkpoint reference (all share the same checkpoint data)
|
|
2896
2909
|
const checkpointRef = allApprovals[0]!;
|
|
2897
2910
|
|
|
2898
|
-
|
|
2911
|
+
const resumeWork = (async () => {
|
|
2899
2912
|
const toolContext = {
|
|
2900
2913
|
runId: checkpointRef.runId,
|
|
2901
2914
|
agentId: identity.id,
|
|
@@ -2943,6 +2956,9 @@ export const createRequestHandler = async (options?: {
|
|
|
2943
2956
|
toolResults,
|
|
2944
2957
|
);
|
|
2945
2958
|
})();
|
|
2959
|
+
if (waitUntilHook) {
|
|
2960
|
+
waitUntilHook(resumeWork);
|
|
2961
|
+
}
|
|
2946
2962
|
|
|
2947
2963
|
writeJson(response, 200, { ok: true, approvalId, approved, batchComplete: true });
|
|
2948
2964
|
return;
|
|
@@ -3057,7 +3073,7 @@ export const createRequestHandler = async (options?: {
|
|
|
3057
3073
|
}
|
|
3058
3074
|
}
|
|
3059
3075
|
const activeStream = conversationEventStreams.get(conversationId);
|
|
3060
|
-
const hasActiveRun = !!activeStream && !activeStream.finished;
|
|
3076
|
+
const hasActiveRun = (!!activeStream && !activeStream.finished) || conversation.runStatus === "running";
|
|
3061
3077
|
writeJson(response, 200, {
|
|
3062
3078
|
conversation: {
|
|
3063
3079
|
...conversation,
|
package/src/web-ui-client.ts
CHANGED
|
@@ -962,8 +962,7 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
962
962
|
setStreaming(true);
|
|
963
963
|
streamConversationEvents(conversationId, { liveOnly: true }).finally(() => {
|
|
964
964
|
if (state.activeConversationId === conversationId) {
|
|
965
|
-
|
|
966
|
-
renderMessages(state.activeMessages, false);
|
|
965
|
+
pollUntilRunIdle(conversationId);
|
|
967
966
|
}
|
|
968
967
|
});
|
|
969
968
|
}
|
|
@@ -1030,6 +1029,30 @@ export const getWebUiClientScript = (markedSource: string): string => `
|
|
|
1030
1029
|
});
|
|
1031
1030
|
};
|
|
1032
1031
|
|
|
1032
|
+
const pollUntilRunIdle = (conversationId) => {
|
|
1033
|
+
const poll = async () => {
|
|
1034
|
+
if (state.activeConversationId !== conversationId) return;
|
|
1035
|
+
try {
|
|
1036
|
+
var payload = await api("/api/conversations/" + encodeURIComponent(conversationId));
|
|
1037
|
+
if (state.activeConversationId !== conversationId) return;
|
|
1038
|
+
if (payload.conversation) {
|
|
1039
|
+
state.activeMessages = payload.conversation.messages || [];
|
|
1040
|
+
renderMessages(state.activeMessages, payload.hasActiveRun);
|
|
1041
|
+
}
|
|
1042
|
+
if (payload.hasActiveRun) {
|
|
1043
|
+
setTimeout(poll, 2000);
|
|
1044
|
+
} else {
|
|
1045
|
+
setStreaming(false);
|
|
1046
|
+
renderMessages(state.activeMessages, false);
|
|
1047
|
+
}
|
|
1048
|
+
} catch {
|
|
1049
|
+
setStreaming(false);
|
|
1050
|
+
renderMessages(state.activeMessages, false);
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
setTimeout(poll, 1500);
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1033
1056
|
const streamConversationEvents = (conversationId, options) => {
|
|
1034
1057
|
const liveOnly = options && options.liveOnly;
|
|
1035
1058
|
return new Promise((resolve) => {
|