@agent-native/creative-context 0.1.0 → 0.3.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/agent-native.package.json +11 -0
- package/dist/actions/continue-context-import.d.ts +16 -1
- package/dist/actions/continue-context-import.js +4 -1
- package/dist/actions/continue-context-import.js.map +1 -1
- package/dist/actions/get-creative-context.d.ts +38 -0
- package/dist/actions/get-creative-context.d.ts.map +1 -1
- package/dist/actions/get-creative-context.js +59 -23
- package/dist/actions/get-creative-context.js.map +1 -1
- package/dist/actions/get-google-picker-session.d.ts +10 -0
- package/dist/actions/get-google-picker-session.d.ts.map +1 -0
- package/dist/actions/get-google-picker-session.js +38 -0
- package/dist/actions/get-google-picker-session.js.map +1 -0
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +2 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/start-context-enrichment.d.ts +16 -1
- package/dist/actions/start-context-enrichment.js +6 -4
- package/dist/actions/start-context-enrichment.js.map +1 -1
- package/dist/actions/start-context-import.d.ts +16 -1
- package/dist/actions/start-context-import.js +2 -1
- package/dist/actions/start-context-import.js.map +1 -1
- package/dist/client/CreativeContextPanel.d.ts +1 -59
- package/dist/client/CreativeContextPanel.d.ts.map +1 -1
- package/dist/client/CreativeContextPanel.js +111 -36
- package/dist/client/CreativeContextPanel.js.map +1 -1
- package/dist/client/actions.d.ts +8 -0
- package/dist/client/actions.d.ts.map +1 -1
- package/dist/client/actions.js +4 -0
- package/dist/client/actions.js.map +1 -1
- package/dist/client/google-slides-picker.d.ts +19 -0
- package/dist/client/google-slides-picker.d.ts.map +1 -0
- package/dist/client/google-slides-picker.js +106 -0
- package/dist/client/google-slides-picker.js.map +1 -0
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/messages.d.ts +1 -1
- package/dist/client/messages.d.ts.map +1 -1
- package/dist/client/messages.js +22 -0
- package/dist/client/messages.js.map +1 -1
- package/dist/connectors/google-slides.d.ts +1 -1
- package/dist/connectors/google-slides.d.ts.map +1 -1
- package/dist/connectors/google-slides.js +1 -2
- package/dist/connectors/google-slides.js.map +1 -1
- package/dist/connectors/normalize.d.ts +7 -0
- package/dist/connectors/normalize.d.ts.map +1 -1
- package/dist/connectors/normalize.js +122 -3
- package/dist/connectors/normalize.js.map +1 -1
- package/dist/schema/index.d.ts +30 -30
- package/dist/server/enrichment.d.ts +1 -0
- package/dist/server/enrichment.d.ts.map +1 -1
- package/dist/server/enrichment.js +26 -24
- package/dist/server/enrichment.js.map +1 -1
- package/dist/server/generation-context.d.ts +1 -1
- package/dist/server/generation-context.d.ts.map +1 -1
- package/dist/server/generation-context.js +1 -1
- package/dist/server/generation-context.js.map +1 -1
- package/dist/store/content.d.ts +13 -0
- package/dist/store/content.d.ts.map +1 -1
- package/dist/store/content.js +172 -1
- package/dist/store/content.js.map +1 -1
- package/dist/store/jobs.d.ts.map +1 -1
- package/dist/store/jobs.js +2 -2
- package/dist/store/jobs.js.map +1 -1
- package/dist/store/purge.d.ts.map +1 -1
- package/dist/store/purge.js +9 -8
- package/dist/store/purge.js.map +1 -1
- package/dist/store/suggestions.d.ts +1 -0
- package/dist/store/suggestions.d.ts.map +1 -1
- package/dist/store/suggestions.js +56 -38
- package/dist/store/suggestions.js.map +1 -1
- package/docs/skills/creative-context/SKILL.md +8 -0
- package/package.json +3 -3
- package/src/actions/continue-context-import.ts +4 -1
- package/src/actions/creative-context-a2a.spec.ts +98 -0
- package/src/actions/get-creative-context.spec.ts +121 -1
- package/src/actions/get-creative-context.ts +78 -29
- package/src/actions/get-google-picker-session.spec.ts +62 -0
- package/src/actions/get-google-picker-session.ts +45 -0
- package/src/actions/index.ts +2 -0
- package/src/actions/job-public-serialization.spec.ts +122 -0
- package/src/actions/start-context-enrichment.ts +6 -4
- package/src/actions/start-context-import.ts +2 -1
- package/src/client/CreativeContextPanel.tsx +163 -64
- package/src/client/actions.ts +18 -0
- package/src/client/google-slides-picker.spec.ts +36 -0
- package/src/client/google-slides-picker.ts +146 -0
- package/src/client/index.ts +2 -0
- package/src/client/messages.ts +35 -0
- package/src/client/source-config.spec.ts +24 -10
- package/src/connectors/google-slides.ts +1 -2
- package/src/connectors/normalize.spec.ts +144 -0
- package/src/connectors/normalize.ts +201 -3
- package/src/server/enrichment.spec.ts +94 -0
- package/src/server/enrichment.ts +27 -24
- package/src/server/generation-artifact-access.spec.ts +104 -0
- package/src/server/generation-context-a2a.spec.ts +20 -2
- package/src/server/generation-context.ts +6 -6
- package/src/server/isolated-a2a.spec.ts +21 -1
- package/src/store/access.integration.spec.ts +511 -26
- package/src/store/content.ts +213 -1
- package/src/store/jobs.ts +2 -0
- package/src/store/purge.ts +18 -9
- package/src/store/suggestions.ts +67 -41
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
|
|
3
|
+
const mocks = vi.hoisted(() => ({
|
|
4
|
+
assertAccess: vi.fn(),
|
|
5
|
+
getRequestUserEmail: vi.fn(),
|
|
6
|
+
getRequestOrgId: vi.fn(),
|
|
7
|
+
}));
|
|
8
|
+
|
|
9
|
+
vi.mock("@agent-native/core/sharing", () => ({
|
|
10
|
+
assertAccess: mocks.assertAccess,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
vi.mock("@agent-native/core/server/request-context", () => ({
|
|
14
|
+
getRequestUserEmail: mocks.getRequestUserEmail,
|
|
15
|
+
getRequestOrgId: mocks.getRequestOrgId,
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
assertGenerationArtifactAccessProof,
|
|
20
|
+
createGenerationArtifactAccessCapability,
|
|
21
|
+
verifyGenerationArtifactAccessCapability,
|
|
22
|
+
} from "./generation-artifact-access.js";
|
|
23
|
+
|
|
24
|
+
const originalKey = process.env.CREATIVE_CONTEXT_A2A_KEY;
|
|
25
|
+
const identity = {
|
|
26
|
+
appId: "slides",
|
|
27
|
+
artifactType: "deck",
|
|
28
|
+
artifactId: "deck-1",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
describe("generation artifact access capabilities", () => {
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
vi.clearAllMocks();
|
|
34
|
+
process.env.CREATIVE_CONTEXT_A2A_KEY = "test-capability-signing-key";
|
|
35
|
+
mocks.getRequestUserEmail.mockReturnValue("alice@example.test");
|
|
36
|
+
mocks.getRequestOrgId.mockReturnValue("org-1");
|
|
37
|
+
mocks.assertAccess.mockResolvedValue({ role: "editor" });
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterEach(() => {
|
|
41
|
+
if (originalKey === undefined) delete process.env.CREATIVE_CONTEXT_A2A_KEY;
|
|
42
|
+
else process.env.CREATIVE_CONTEXT_A2A_KEY = originalKey;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("mints a short-lived capability only after host artifact access succeeds", async () => {
|
|
46
|
+
const token = await createGenerationArtifactAccessCapability(
|
|
47
|
+
identity,
|
|
48
|
+
{ resourceType: "deck", resourceId: "deck-1" },
|
|
49
|
+
"record",
|
|
50
|
+
);
|
|
51
|
+
expect(mocks.assertAccess).toHaveBeenCalledWith(
|
|
52
|
+
"deck",
|
|
53
|
+
"deck-1",
|
|
54
|
+
"editor",
|
|
55
|
+
undefined,
|
|
56
|
+
{ skipResourceBody: true },
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const proof = await verifyGenerationArtifactAccessCapability(
|
|
60
|
+
token,
|
|
61
|
+
identity,
|
|
62
|
+
"record",
|
|
63
|
+
);
|
|
64
|
+
expect(() =>
|
|
65
|
+
assertGenerationArtifactAccessProof(identity, proof, "editor"),
|
|
66
|
+
).not.toThrow();
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("binds the capability to caller, artifact identity, and operation", async () => {
|
|
70
|
+
const token = await createGenerationArtifactAccessCapability(
|
|
71
|
+
identity,
|
|
72
|
+
{ resourceType: "deck", resourceId: "deck-1" },
|
|
73
|
+
"read",
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
await expect(
|
|
77
|
+
verifyGenerationArtifactAccessCapability(
|
|
78
|
+
token,
|
|
79
|
+
{ ...identity, artifactId: "guessed-deck" },
|
|
80
|
+
"read",
|
|
81
|
+
),
|
|
82
|
+
).rejects.toThrow(/invalid generation artifact access capability/i);
|
|
83
|
+
await expect(
|
|
84
|
+
verifyGenerationArtifactAccessCapability(token, identity, "record"),
|
|
85
|
+
).rejects.toThrow(/invalid generation artifact access capability/i);
|
|
86
|
+
mocks.getRequestUserEmail.mockReturnValue("mallory@example.test");
|
|
87
|
+
await expect(
|
|
88
|
+
verifyGenerationArtifactAccessCapability(token, identity, "read"),
|
|
89
|
+
).rejects.toThrow(/invalid generation artifact access capability/i);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("rejects forged capability bytes", async () => {
|
|
93
|
+
const token = await createGenerationArtifactAccessCapability(
|
|
94
|
+
identity,
|
|
95
|
+
{ resourceType: "deck", resourceId: "deck-1" },
|
|
96
|
+
"read",
|
|
97
|
+
);
|
|
98
|
+
const forged = `${token.slice(0, -1)}${token.endsWith("a") ? "b" : "a"}`;
|
|
99
|
+
|
|
100
|
+
await expect(
|
|
101
|
+
verifyGenerationArtifactAccessCapability(forged, identity, "read"),
|
|
102
|
+
).rejects.toThrow(/invalid generation artifact access capability/i);
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -10,12 +10,18 @@ const mocks = vi.hoisted(() => ({
|
|
|
10
10
|
getLocal: vi.fn(),
|
|
11
11
|
hasA2A: vi.fn(),
|
|
12
12
|
callA2A: vi.fn(),
|
|
13
|
+
getRequestOrgId: vi.fn(),
|
|
14
|
+
createArtifactCapability: vi.fn(),
|
|
13
15
|
}));
|
|
14
16
|
|
|
15
17
|
vi.mock("@agent-native/core/application-state", () => ({
|
|
16
18
|
readAppState: mocks.readAppState,
|
|
17
19
|
}));
|
|
18
20
|
|
|
21
|
+
vi.mock("@agent-native/core/server/request-context", () => ({
|
|
22
|
+
getRequestOrgId: mocks.getRequestOrgId,
|
|
23
|
+
}));
|
|
24
|
+
|
|
19
25
|
vi.mock("../store/index.js", () => ({
|
|
20
26
|
getContextPack: mocks.getContextPack,
|
|
21
27
|
getCreativeContextItem: mocks.getCreativeContextItem,
|
|
@@ -43,6 +49,11 @@ vi.mock("./isolated-a2a.js", () => ({
|
|
|
43
49
|
})),
|
|
44
50
|
}));
|
|
45
51
|
|
|
52
|
+
vi.mock("./generation-artifact-access.js", () => ({
|
|
53
|
+
assertGenerationArtifactAccess: vi.fn(),
|
|
54
|
+
createGenerationArtifactAccessCapability: mocks.createArtifactCapability,
|
|
55
|
+
}));
|
|
56
|
+
|
|
46
57
|
import {
|
|
47
58
|
getGenerationCreativeContext,
|
|
48
59
|
recordGenerationCreativeContext,
|
|
@@ -62,6 +73,10 @@ describe("generation context isolated A2A routing", () => {
|
|
|
62
73
|
vi.clearAllMocks();
|
|
63
74
|
mocks.readAppState.mockResolvedValue({ contextMode: "auto" });
|
|
64
75
|
mocks.hasA2A.mockReturnValue(true);
|
|
76
|
+
mocks.getRequestOrgId.mockReturnValue("org-1");
|
|
77
|
+
mocks.createArtifactCapability.mockImplementation(
|
|
78
|
+
async (_identity, _target, operation) => `cap-${operation}`,
|
|
79
|
+
);
|
|
65
80
|
mocks.callA2A.mockResolvedValue(emptyRemoteContext);
|
|
66
81
|
});
|
|
67
82
|
|
|
@@ -104,12 +119,15 @@ describe("generation context isolated A2A routing", () => {
|
|
|
104
119
|
artifactType: "deck",
|
|
105
120
|
artifactId: "deck-1",
|
|
106
121
|
},
|
|
107
|
-
|
|
122
|
+
artifactAccessCapability: "cap-read",
|
|
108
123
|
});
|
|
109
124
|
expect(mocks.callA2A).toHaveBeenNthCalledWith(
|
|
110
125
|
4,
|
|
111
126
|
"record",
|
|
112
|
-
expect.objectContaining({
|
|
127
|
+
expect.objectContaining({
|
|
128
|
+
artifactId: "deck-1",
|
|
129
|
+
artifactAccessCapability: "cap-record",
|
|
130
|
+
}),
|
|
113
131
|
);
|
|
114
132
|
expect(mocks.recordLocal).not.toHaveBeenCalled();
|
|
115
133
|
expect(mocks.getLocal).not.toHaveBeenCalled();
|
|
@@ -14,18 +14,18 @@ import type {
|
|
|
14
14
|
CreativeContextElementProvenance,
|
|
15
15
|
CreativeContextReuseLabel,
|
|
16
16
|
} from "../types.js";
|
|
17
|
-
import {
|
|
18
|
-
callIsolatedCreativeContextA2A,
|
|
19
|
-
hasIsolatedCreativeContextA2A,
|
|
20
|
-
isolatedResolvePayload,
|
|
21
|
-
type IsolatedRecordPayload,
|
|
22
|
-
} from "./isolated-a2a.js";
|
|
23
17
|
import {
|
|
24
18
|
assertGenerationArtifactAccess,
|
|
25
19
|
createGenerationArtifactAccessCapability,
|
|
26
20
|
type GenerationArtifactAccessTarget,
|
|
27
21
|
type GenerationArtifactIdentity,
|
|
28
22
|
} from "./generation-artifact-access.js";
|
|
23
|
+
import {
|
|
24
|
+
callIsolatedCreativeContextA2A,
|
|
25
|
+
hasIsolatedCreativeContextA2A,
|
|
26
|
+
isolatedResolvePayload,
|
|
27
|
+
type IsolatedRecordPayload,
|
|
28
|
+
} from "./isolated-a2a.js";
|
|
29
29
|
import { performCreativeContextSearch } from "./retrieval.js";
|
|
30
30
|
import {
|
|
31
31
|
sanitizeUntrustedReference,
|
|
@@ -141,7 +141,6 @@ describe("isolated Creative Context A2A", () => {
|
|
|
141
141
|
artifactType: "deck",
|
|
142
142
|
artifactId: "deck-1",
|
|
143
143
|
},
|
|
144
|
-
accessScope: "owner",
|
|
145
144
|
},
|
|
146
145
|
{
|
|
147
146
|
callAgent: vi.fn(async () => {
|
|
@@ -154,6 +153,27 @@ describe("isolated Creative Context A2A", () => {
|
|
|
154
153
|
);
|
|
155
154
|
});
|
|
156
155
|
|
|
156
|
+
it("rejects the retired caller-selectable collaborative read scope", () => {
|
|
157
|
+
const requestToken = Buffer.from(
|
|
158
|
+
JSON.stringify({
|
|
159
|
+
protocol: "creative-context-a2a-v1",
|
|
160
|
+
requestId: "87f466ae-32f4-4d0f-9de7-96f955e69f7b",
|
|
161
|
+
operation: "read",
|
|
162
|
+
payload: {
|
|
163
|
+
identity: {
|
|
164
|
+
appId: "slides",
|
|
165
|
+
artifactType: "deck",
|
|
166
|
+
artifactId: "guessed-deck",
|
|
167
|
+
},
|
|
168
|
+
accessScope: "artifact-access-asserted",
|
|
169
|
+
},
|
|
170
|
+
}),
|
|
171
|
+
"utf8",
|
|
172
|
+
).toString("base64url");
|
|
173
|
+
|
|
174
|
+
expect(() => decodeCreativeContextA2ARequest(requestToken)).toThrow();
|
|
175
|
+
});
|
|
176
|
+
|
|
157
177
|
it("fails closed when the isolated URL has no signing secret", async () => {
|
|
158
178
|
delete process.env.CREATIVE_CONTEXT_A2A_KEY;
|
|
159
179
|
delete process.env.A2A_SECRET;
|