@hassangameryt/freeflow 0.7.2 → 0.7.3
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/README.md +147 -127
- package/capabilities/cognitive-routing/SKILL.md +162 -93
- package/gemini-extension.json +1 -1
- package/package.json +1 -1
- package/pi-extension/dist/cognitive-routing-v2/config.js +35 -19
- package/pi-extension/dist/cognitive-routing-v2/projection.js +53 -44
- package/pi-extension/dist/cognitive-routing-v2/render.js +31 -10
- package/pi-extension/dist/cognitive-routing-v2/runtime.js +701 -105
- package/pi-extension/dist/cognitive-routing-v2/schemas.js +90 -24
- package/pi-extension/dist/cognitive-routing-v2/state.js +243 -27
- package/pi-extension/dist/cognitive-routing-v2/tools.js +19 -50
- package/pi-extension/dist/cognitive-routing-v2/types.js +5 -1
- package/pi-extension/dist/context-virtualization/runtime.js +29 -7
- package/pi-extension/dist/freeflow-context/tool.js +7 -6
- package/pi-extension/dist/index.js +36 -15
- package/pi-extension/dist/provider-support/astra/adapter.js +110 -0
- package/pi-extension/dist/provider-support/astra/history.js +125 -0
- package/pi-extension/dist/provider-support/astra/index.js +11 -0
- package/pi-extension/dist/provider-support/astra/session-state.js +114 -0
- package/pi-extension/dist/provider-support/index.js +4 -0
- package/pi-extension/dist/runtime/request-history.js +216 -0
- package/pi-extension/dist/runtime/runtime-context.js +29 -10
- package/pi-extension/dist/session-sources/events.js +22 -0
- package/pi-extension/dist/session-sources/provenance.js +32 -0
- package/pi-extension/dist/session-sources/sources.js +51 -7
- package/pi-extension/dist/settings/settings-ui.js +247 -47
- package/pi-extension/src/cognitive-routing-v2/config.ts +49 -19
- package/pi-extension/src/cognitive-routing-v2/projection.ts +53 -43
- package/pi-extension/src/cognitive-routing-v2/render.ts +31 -10
- package/pi-extension/src/cognitive-routing-v2/runtime.ts +712 -105
- package/pi-extension/src/cognitive-routing-v2/schemas.ts +95 -24
- package/pi-extension/src/cognitive-routing-v2/state.ts +244 -27
- package/pi-extension/src/cognitive-routing-v2/tools.ts +19 -50
- package/pi-extension/src/cognitive-routing-v2/types.ts +35 -3
- package/pi-extension/src/context-virtualization/runtime.ts +30 -8
- package/pi-extension/src/freeflow-context/tool.ts +7 -6
- package/pi-extension/src/index.ts +36 -14
- package/pi-extension/src/provider-support/astra/adapter.ts +108 -0
- package/pi-extension/src/provider-support/astra/history.ts +145 -0
- package/pi-extension/src/provider-support/astra/index.ts +12 -0
- package/pi-extension/src/provider-support/astra/session-state.ts +113 -0
- package/pi-extension/src/provider-support/index.ts +5 -0
- package/pi-extension/src/runtime/request-history.ts +243 -0
- package/pi-extension/src/runtime/runtime-context.ts +32 -10
- package/pi-extension/src/session-sources/events.ts +22 -0
- package/pi-extension/src/session-sources/provenance.ts +39 -0
- package/pi-extension/src/session-sources/sources.ts +77 -6
- package/pi-extension/src/settings/settings-ui.ts +276 -46
- package/pi-extension/tests/cache-reuse/history.test.js +117 -0
- package/pi-extension/tests/cache-reuse/native.test.js +91 -0
- package/pi-extension/tests/cache-reuse/settings.test.js +211 -0
- package/pi-extension/tests/cognitive-routing-v2/communication.test.js +94 -1
- package/pi-extension/tests/cognitive-routing-v2/delegation.test.js +557 -0
- package/pi-extension/tests/cognitive-routing-v2/native.test.js +34 -1
- package/pi-extension/tests/cognitive-routing-v2/persistence.test.js +55 -0
- package/pi-extension/tests/cognitive-routing-v2/recovery.test.js +800 -2
- package/pi-extension/tests/cognitive-routing-v2/render.test.js +15 -1
- package/pi-extension/tests/cognitive-routing-v2/runtime.test.js +273 -3
- package/pi-extension/tests/cognitive-routing-v2/state.test.js +312 -1
- package/pi-extension/tests/context-virtualization/extension.test.js +20 -10
- package/pi-extension/tests/context-virtualization/runtime.test.js +17 -3
- package/pi-extension/tests/fixtures/routing-native.js +4 -1
- package/pi-extension/tests/integration/mode-free-core.test.js +4 -3
- package/pi-extension/tests/integration/pi-extension.test.js +508 -29
- package/pi-extension/tests/integration/prompt-architecture.test.js +56 -40
- package/pi-extension/tests/integration/unaffected-regressions.test.js +3 -3
- package/pi-extension/tests/provider-support/astra-boundaries.test.js +75 -0
- package/pi-extension/tests/provider-support/astra.test.js +306 -0
- package/pi-extension/tests/provider-support/cli.test.js +92 -0
- package/pi-extension/tests/provider-support/native.test.js +183 -0
- package/plugin.json +1 -1
- package/runtime/prompts/cognitive-routing.md +4 -4
- package/skills/design-for-depth/SKILL.md +1 -1
- package/skills/design-for-depth/references/implementation-decisions.md +3 -3
- package/skills/discuss/SKILL.md +2 -2
|
@@ -169,7 +169,7 @@ function renderComponent(component) {
|
|
|
169
169
|
return component.render(120).join("\\n");
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
test("disabled Freeflow Context
|
|
172
|
+
test("disabled Freeflow Context retains valid full operation schemas", async () => {
|
|
173
173
|
const cwd = await mkdtemp(join(tmpdir(), "freeflow-context-disabled-schema-"));
|
|
174
174
|
try {
|
|
175
175
|
await writeConfig(cwd, {});
|
|
@@ -178,8 +178,17 @@ test("disabled Freeflow Context does not publish an empty oneOf schema", async (
|
|
|
178
178
|
|
|
179
179
|
const contextTool = harness.tools.find((tool) => tool.name === "freeflow_context");
|
|
180
180
|
assert.ok(contextTool);
|
|
181
|
-
assert.
|
|
182
|
-
assert.
|
|
181
|
+
assert.equal(contextTool.parameters.type, "object");
|
|
182
|
+
assert.deepEqual(
|
|
183
|
+
contextTool.parameters.oneOf.map((v) => v.properties.operation.const),
|
|
184
|
+
["archive", "restore", "search", "retrieve"],
|
|
185
|
+
);
|
|
186
|
+
const denied = await contextTool.execute(
|
|
187
|
+
"disabled",
|
|
188
|
+
{ operation: "archive", targets: [{ ref: "ctx:tool-1" }] },
|
|
189
|
+
undefined,
|
|
190
|
+
);
|
|
191
|
+
assert.equal(denied.details.result.status, "rejected");
|
|
183
192
|
} finally {
|
|
184
193
|
await rm(cwd, { recursive: true, force: true });
|
|
185
194
|
}
|
|
@@ -205,7 +214,7 @@ test("enabled Context Virtualization registers, projects, archives, restores, an
|
|
|
205
214
|
|
|
206
215
|
const contextTool = harness.tools.find((tool) => tool.name === "freeflow_context");
|
|
207
216
|
assert.ok(contextTool);
|
|
208
|
-
assert.
|
|
217
|
+
assert.match(contextTool.description, /conversation history/i);
|
|
209
218
|
const staleSearch = await contextTool.execute(
|
|
210
219
|
"context-stale-search",
|
|
211
220
|
{ operation: "search", query: "not enabled" },
|
|
@@ -291,7 +300,7 @@ test("enabled Context Virtualization registers, projects, archives, restores, an
|
|
|
291
300
|
}
|
|
292
301
|
});
|
|
293
302
|
|
|
294
|
-
test("enabled Conversation History
|
|
303
|
+
test("enabled Conversation History permits search and retrieve within the stable catalog", async () => {
|
|
295
304
|
const cwd = await mkdtemp(join(tmpdir(), "freeflow-conversation-history-extension-"));
|
|
296
305
|
try {
|
|
297
306
|
await writeConfig(cwd, { conversationHistory: true });
|
|
@@ -303,7 +312,7 @@ test("enabled Conversation History exposes only search and retrieve operations",
|
|
|
303
312
|
assert.ok(contextTool);
|
|
304
313
|
assert.deepEqual(
|
|
305
314
|
contextTool.parameters.oneOf.map((variant) => variant.properties.operation.const),
|
|
306
|
-
["search", "retrieve"],
|
|
315
|
+
["archive", "restore", "search", "retrieve"],
|
|
307
316
|
);
|
|
308
317
|
assert.equal(typeof contextTool.renderCall, "function");
|
|
309
318
|
assert.equal(typeof contextTool.renderResult, "function");
|
|
@@ -365,7 +374,7 @@ test("enabled Conversation History exposes only search and retrieve operations",
|
|
|
365
374
|
assert.match(renderComponent(expandedResult), /ctx:render-source/);
|
|
366
375
|
assert.match(renderComponent(expandedResult), /database timeout was recovered/);
|
|
367
376
|
assert.match(contextTool.description, /hidden conversation history/i);
|
|
368
|
-
assert.
|
|
377
|
+
assert.match(contextTool.description, /future context projections/i);
|
|
369
378
|
const before = await harness.handlers.get("before_agent_start")({ systemPrompt: "base" }, harness.ctx);
|
|
370
379
|
assert.match(before.systemPrompt, /## Conversation History Cue/);
|
|
371
380
|
assert.doesNotMatch(before.systemPrompt, /# Conversation History$/m);
|
|
@@ -744,20 +753,21 @@ test("visible invalid sources do not make an empty hidden corpus partial", async
|
|
|
744
753
|
}
|
|
745
754
|
});
|
|
746
755
|
|
|
747
|
-
test("disabled Context Virtualization
|
|
756
|
+
test("disabled Context Virtualization blocks execution while preserving definitions and reference labels", async () => {
|
|
748
757
|
const cwd = await mkdtemp(join(tmpdir(), "freeflow-context-disabled-"));
|
|
749
758
|
try {
|
|
750
759
|
await writeConfig(cwd, false);
|
|
751
760
|
const harness = createHarness(cwd, [toolResultEntry()]);
|
|
752
761
|
await harness.handlers.get("session_start")({ reason: "startup" }, harness.ctx);
|
|
753
762
|
|
|
754
|
-
assert.ok(
|
|
763
|
+
assert.ok(harness.activeToolNames().includes("freeflow_context"));
|
|
755
764
|
const contextResult = await harness.handlers.get("context")(
|
|
756
765
|
{ messages: [harness.entries[0].message] },
|
|
757
766
|
harness.ctx,
|
|
758
767
|
);
|
|
759
768
|
assert.ok(contextResult);
|
|
760
|
-
assert.deepEqual(contextResult.messages[0], harness.entries[0].message);
|
|
769
|
+
assert.deepEqual(contextResult.messages[0].content.slice(0, -1), harness.entries[0].message.content);
|
|
770
|
+
assert.match(contextResult.messages[0].content.at(-1).text, /context-ref:/);
|
|
761
771
|
assert.equal(contextResult.messages.at(-1).customType, "freeflow-runtime-state");
|
|
762
772
|
} finally {
|
|
763
773
|
await rm(cwd, { recursive: true, force: true });
|
|
@@ -208,9 +208,23 @@ test("mutation persistence failure returns an error without publishing projectio
|
|
|
208
208
|
assert.match(next.messages[0].content.at(-1).text, /ctx:tool-1/);
|
|
209
209
|
});
|
|
210
210
|
|
|
211
|
-
test("disabled projection
|
|
211
|
+
test("disabled projection keeps original content and the stable reference marker", async () => {
|
|
212
212
|
const { runtime } = createFixture();
|
|
213
213
|
const result = await runtime.project([toolMessage()], false);
|
|
214
|
-
assert.equal(result.changed,
|
|
215
|
-
assert.deepEqual(result.messages[0].content, [{ type: "text", text: "secret raw output" }]);
|
|
214
|
+
assert.equal(result.changed, true);
|
|
215
|
+
assert.deepEqual(result.messages[0].content.slice(0, -1), [{ type: "text", text: "secret raw output" }]);
|
|
216
|
+
assert.match(result.messages[0].content.at(-1).text, /context-ref: ctx:tool-1/);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
test("unavailable decoration leaves the already projected view intact", () => {
|
|
220
|
+
const { runtime } = createFixture();
|
|
221
|
+
runtime.setContext({
|
|
222
|
+
sessionManager: {
|
|
223
|
+
getBranch() {
|
|
224
|
+
throw Error("unavailable");
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
const current = [{ role: "custom", customType: "blocked", content: "Only this safe view" }];
|
|
229
|
+
assert.equal(runtime.decorate(current), current);
|
|
216
230
|
});
|
|
@@ -69,7 +69,7 @@ export async function fixture(script, projection = true, after, withUI = true, o
|
|
|
69
69
|
await writeFile(
|
|
70
70
|
join(cwd, ".freeflow/config.json"),
|
|
71
71
|
JSON.stringify({
|
|
72
|
-
cognitiveRouting: {
|
|
72
|
+
cognitiveRouting: options.cognitiveRouting ?? {
|
|
73
73
|
enabled: true,
|
|
74
74
|
projection,
|
|
75
75
|
profiles: {
|
|
@@ -81,6 +81,8 @@ export async function fixture(script, projection = true, after, withUI = true, o
|
|
|
81
81
|
);
|
|
82
82
|
await writeFile(join(cwd, "evidence.txt"), "EXACT_EVIDENCE_BODY_81");
|
|
83
83
|
await writeFile(join(cwd, "unselected.txt"), "UNSELECTED_PRIVATE_BODY_93");
|
|
84
|
+
await writeFile(join(cwd, "recovery.txt"), "FRESH_RECOVERY_BODY_57");
|
|
85
|
+
await writeFile(join(cwd, "@recovery.txt"), "LITERAL_AT_FILE_BODY_68");
|
|
84
86
|
await writeFile(
|
|
85
87
|
join(agentDir, "models.json"),
|
|
86
88
|
JSON.stringify({ providers: { openai: { baseUrl: "https://fixture.invalid/v1" } } }),
|
|
@@ -166,6 +168,7 @@ export async function fixture(script, projection = true, after, withUI = true, o
|
|
|
166
168
|
...(withUI ? { uiContext: { notify: (...args) => notices.push(args), setStatus: () => {} } } : {}),
|
|
167
169
|
});
|
|
168
170
|
await options.onSession?.(session);
|
|
171
|
+
await options.beforePrompt?.({ session, manager, requests, contexts, cwd, notices });
|
|
169
172
|
await session.prompt("Complete the fixture assignment.");
|
|
170
173
|
await session.waitForIdle();
|
|
171
174
|
assert.deepEqual(errors, [], "extension lifecycle errors");
|
|
@@ -138,7 +138,7 @@ test("Pi exposes base skills without mode or Skills controls", async () => {
|
|
|
138
138
|
const { handlers, commands } = loadExtension();
|
|
139
139
|
const ctx = context(cwd);
|
|
140
140
|
const resources = await handlers.get("resources_discover")({ cwd }, ctx);
|
|
141
|
-
assert.equal(resources.skillPaths.length,
|
|
141
|
+
assert.equal(resources.skillPaths.length, 27);
|
|
142
142
|
assert.ok(resources.skillPaths.some((path) => path.endsWith("/skills/workflow/SKILL.md")));
|
|
143
143
|
assert.ok(!resources.skillPaths.some((path) => path.endsWith("/skills/tdd/SKILL.md")));
|
|
144
144
|
assert.ok(!resources.skillPaths.some((path) => path.endsWith("/skills/mode-contract/SKILL.md")));
|
|
@@ -181,9 +181,10 @@ test("mandatory prompt readiness gates Runtime State, discovery, and direct skil
|
|
|
181
181
|
const { handlers, commands, sentMessages } = loadExtension(extension);
|
|
182
182
|
const ctx = context(cwd);
|
|
183
183
|
const before = await handlers.get("before_agent_start")({ systemPrompt: "base prompt" }, ctx);
|
|
184
|
-
assert.
|
|
184
|
+
assert.ok(before.systemPrompt.startsWith("base prompt\n\n"));
|
|
185
|
+
assert.match(before.systemPrompt, /guidance is dormant/);
|
|
185
186
|
const resources = await handlers.get("resources_discover")({ cwd }, ctx);
|
|
186
|
-
assert.
|
|
187
|
+
assert.equal(resources.skillPaths.length, 27);
|
|
187
188
|
|
|
188
189
|
const discuss = commands.find((command) => command.name === "discuss");
|
|
189
190
|
assert.ok(discuss);
|