@hasna/instructions 0.7.0 → 0.7.2
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/README.md +52 -11
- package/dist/chunks/{apply-7svah2qm.js → apply-ps6jjt6k.js} +3 -3
- package/dist/chunks/{apply-jp13sa1e.js → apply-wj7wh5km.js} +3 -3
- package/dist/chunks/{index-1cnyjnd7.js → index-18j7x3xw.js} +2 -2
- package/dist/chunks/{index-3djthcm6.js → index-27az1qb1.js} +28 -1
- package/dist/chunks/{index-fwbs6tma.js → index-ape24zc0.js} +2 -2
- package/dist/chunks/{index-bzyxvwcd.js → index-ek15201v.js} +2 -2
- package/dist/chunks/{index-arrrx0ed.js → index-mvckkf15.js} +39 -20
- package/dist/chunks/{index-7m4j8a33.js → index-n6nh6f5r.js} +235 -20
- package/dist/chunks/{index-4pfq42t5.js → index-pq18fdbj.js} +146 -32
- package/dist/chunks/{index-n3fjspr0.js → index-preyvj8n.js} +28 -1
- package/dist/chunks/{index-z3ma4aqk.js → index-y8410ve0.js} +3 -3
- package/dist/chunks/{local-5wvv5xv3.js → local-1c1qxzvx.js} +155 -4
- package/dist/chunks/{local-zxa5dpf4.js → local-hc67bynj.js} +155 -4
- package/dist/chunks/{s3-backup-n2z4fwyh.js → s3-backup-hxe3zpfz.js} +1 -1
- package/dist/chunks/{s3-object-store-90tgbh6k.js → s3-object-store-n0s82swt.js} +1 -1
- package/dist/chunks/{sync-r8t7zsp3.js → sync-12m3vs6g.js} +4 -4
- package/dist/chunks/{sync-2075deve.js → sync-azd9t4p8.js} +4 -4
- package/dist/chunks/{template-wgnzdn7h.js → template-e4qrxs8p.js} +1 -1
- package/dist/chunks/{template-fsfxpe4p.js → template-nhn124zd.js} +1 -1
- package/dist/cli/index.js +860 -181
- package/dist/data/config-store.d.ts +22 -6
- package/dist/data/config-store.d.ts.map +1 -1
- package/dist/db/configs.d.ts +4 -1
- package/dist/db/configs.d.ts.map +1 -1
- package/dist/db/local.d.ts +1 -1
- package/dist/db/local.d.ts.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +940 -134
- package/dist/lib/asset-plan.d.ts.map +1 -1
- package/dist/lib/codewith-shared-todos-storage-standard.d.ts.map +1 -1
- package/dist/lib/compact-output.d.ts +2 -18
- package/dist/lib/compact-output.d.ts.map +1 -1
- package/dist/lib/dangerous-operation-guard-standard.d.ts.map +1 -1
- package/dist/lib/export.d.ts.map +1 -1
- package/dist/lib/global-agent-rules-standard.d.ts.map +1 -1
- package/dist/lib/global-source-coverage.d.ts +12 -7
- package/dist/lib/global-source-coverage.d.ts.map +1 -1
- package/dist/lib/import.d.ts.map +1 -1
- package/dist/lib/instruction-graph.d.ts +1 -1
- package/dist/lib/instruction-graph.d.ts.map +1 -1
- package/dist/lib/instruction-source-policy.d.ts +6 -0
- package/dist/lib/instruction-source-policy.d.ts.map +1 -0
- package/dist/lib/platform-profiles.d.ts.map +1 -1
- package/dist/lib/project-dashboard-standard.d.ts.map +1 -1
- package/dist/lib/session-apply.d.ts +24 -0
- package/dist/lib/session-apply.d.ts.map +1 -1
- package/dist/lib/session-refresh.d.ts +30 -0
- package/dist/lib/session-refresh.d.ts.map +1 -0
- package/dist/lib/session-render.d.ts +34 -1
- package/dist/lib/session-render.d.ts.map +1 -1
- package/dist/lib/transforms.d.ts +1 -0
- package/dist/lib/transforms.d.ts.map +1 -1
- package/dist/mcp/index.js +23 -22
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/sdk/index.js +46 -3
- package/dist/sdk/v1-client.d.ts +10 -3
- package/dist/sdk/v1-client.d.ts.map +1 -1
- package/dist/sdk/v1.generated.d.ts +52 -2
- package/dist/sdk/v1.generated.d.ts.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +215 -15
- package/dist/server/openapi.d.ts +240 -3
- package/dist/server/openapi.d.ts.map +1 -1
- package/dist/server/v1.d.ts.map +1 -1
- package/dist/storage/cloud-store.d.ts +2 -15
- package/dist/storage/cloud-store.d.ts.map +1 -1
- package/dist/storage/index.js +39 -20
- package/dist/storage/s3-object-store.d.ts.map +1 -1
- package/dist/types/index.d.ts +49 -2
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/server/index.js
CHANGED
|
@@ -17,12 +17,18 @@ var __export = (target, all) => {
|
|
|
17
17
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
18
18
|
|
|
19
19
|
// src/types/index.ts
|
|
20
|
-
|
|
20
|
+
function validateExpectedConfigVersion(value) {
|
|
21
|
+
if (value !== undefined && (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)) {
|
|
22
|
+
throw new InvalidExpectedVersionError;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
var CONFIG_AGENTS, PROFILE_CONFIG_BINDING_SCHEMA = "hasna.instructions.profile-config-binding/v1", INSTRUCTION_ACTIVATION_MODES, INSTRUCTION_FALLBACKS, PROFILE_ASSET_BINDING_SCHEMA = "hasna.instructions.profile-asset-binding/v1", ASSET_KINDS, ASSET_DESTINATION_STRATEGIES, ASSET_SCOPES, ASSET_UNINSTALL_POLICIES, ASSET_ROLLBACK_POLICIES, InvalidExpectedVersionError, ConfigVersionConflictError, ConfigNotFoundError, ProfileNotFoundError;
|
|
21
26
|
var init_types = __esm(() => {
|
|
22
27
|
CONFIG_AGENTS = [
|
|
23
28
|
"claude",
|
|
24
29
|
"codex",
|
|
25
30
|
"opencode",
|
|
31
|
+
"sumi",
|
|
26
32
|
"cursor",
|
|
27
33
|
"codewith",
|
|
28
34
|
"aicopilot",
|
|
@@ -45,6 +51,25 @@ var init_types = __esm(() => {
|
|
|
45
51
|
ASSET_SCOPES = ["global", "project", "session"];
|
|
46
52
|
ASSET_UNINSTALL_POLICIES = ["remove-managed", "retain"];
|
|
47
53
|
ASSET_ROLLBACK_POLICIES = ["snapshot", "installer-receipt", "none"];
|
|
54
|
+
InvalidExpectedVersionError = class InvalidExpectedVersionError extends Error {
|
|
55
|
+
code = "INVALID_EXPECTED_VERSION";
|
|
56
|
+
constructor() {
|
|
57
|
+
super("expected_version must be a positive safe integer");
|
|
58
|
+
this.name = "InvalidExpectedVersionError";
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
ConfigVersionConflictError = class ConfigVersionConflictError extends Error {
|
|
62
|
+
config_id;
|
|
63
|
+
expected_version;
|
|
64
|
+
code = "CONFIG_VERSION_CONFLICT";
|
|
65
|
+
status = 409;
|
|
66
|
+
constructor(config_id, expected_version) {
|
|
67
|
+
super(`Config version conflict: ${config_id} no longer has expected version ${expected_version}`);
|
|
68
|
+
this.config_id = config_id;
|
|
69
|
+
this.expected_version = expected_version;
|
|
70
|
+
this.name = "ConfigVersionConflictError";
|
|
71
|
+
}
|
|
72
|
+
};
|
|
48
73
|
ConfigNotFoundError = class ConfigNotFoundError extends Error {
|
|
49
74
|
constructor(id) {
|
|
50
75
|
super(`Config not found: ${id}`);
|
|
@@ -104,7 +129,6 @@ function boundedReadPage(items, total, options = {}) {
|
|
|
104
129
|
};
|
|
105
130
|
}
|
|
106
131
|
var init_bounded_read = () => {};
|
|
107
|
-
|
|
108
132
|
// ../../node_modules/.bun/@hasna+contracts@1.0.2+e8014c875821e0be/node_modules/@hasna/contracts/dist/client/transport.js
|
|
109
133
|
import { createRequire } from "module";
|
|
110
134
|
var MAX_CREDENTIAL_FILE_BYTES, INSPECT_CUSTOM, CREDENTIAL_SEAL, AMBIENT_ENVIRONMENT, SECRETS_PACKAGE_SPECIFIER, requireSecretsSdk, IDEMPOTENT_METHODS, AUTHORITY_OVERRIDE_HEADERS;
|
|
@@ -174,6 +198,7 @@ var init_config_store = __esm(() => {
|
|
|
174
198
|
// src/lib/global-agent-rules-standard.ts
|
|
175
199
|
var AGENT_OPERATING_RULES_SOURCE_SET_ID = "hasna-global-agent-rules-standard", AGENT_OPERATING_RULES_SOURCE_ID = "hasna-agent-operating-rules", AGENT_OPERATING_RULES_VERSION = "1.1.26", AGENT_OPERATING_RULES_SOURCE_SET_VERSION = "2026-08-11", AGENT_OPERATING_RULES_PAYLOAD_SHA256 = "486844a3d869e3dabc2f33fd66479d4e2fb0a0d1864a3d8a3dd05669eb3f1b77", AGENT_OPERATING_RULES_UPSTREAM_FILE_SHA256 = "b8e89cdb49e207e5b497ac51384d67022b94fe5645cc9273db60384eb2c2fb32", SCOPED_OPERATIONAL_CONTROL_POLICY_REFERENCE = "hasna-agent-operating-rules/scoped-operational-control/v1", AGENT_OPERATING_RULES_UPSTREAM, SCOPED_OPERATIONAL_CONTROL_POLICY, AGENT_OPERATING_RULES_PROVENANCE, GLOBAL_AGENT_RULES_STANDARD_CONTENT;
|
|
176
200
|
var init_global_agent_rules_standard = __esm(() => {
|
|
201
|
+
init_types();
|
|
177
202
|
init_config_store();
|
|
178
203
|
AGENT_OPERATING_RULES_UPSTREAM = {
|
|
179
204
|
repository: "hasnaxyz/iapp-identities",
|
|
@@ -264,6 +289,7 @@ var init_global_agent_rules_standard = __esm(() => {
|
|
|
264
289
|
// src/lib/codewith-shared-todos-storage-standard.ts
|
|
265
290
|
var CODEWITH_SHARED_TODOS_STORAGE_POLICY_REFERENCE = "codewith/shared-todos-storage/v1", CODEWITH_SHARED_TODOS_STORAGE_STANDARD_CONTENT;
|
|
266
291
|
var init_codewith_shared_todos_storage_standard = __esm(() => {
|
|
292
|
+
init_types();
|
|
267
293
|
init_config_store();
|
|
268
294
|
CODEWITH_SHARED_TODOS_STORAGE_STANDARD_CONTENT = `# Codewith Shared Todos Storage Standard
|
|
269
295
|
|
|
@@ -4717,6 +4743,7 @@ var init_asset_plan = __esm(() => {
|
|
|
4717
4743
|
codex: "cli",
|
|
4718
4744
|
cursor: "ide",
|
|
4719
4745
|
opencode: "cli",
|
|
4746
|
+
sumi: "cli",
|
|
4720
4747
|
codewith: "cli",
|
|
4721
4748
|
qwen: "cli",
|
|
4722
4749
|
aicopilot: "cli",
|
|
@@ -4842,6 +4869,15 @@ var init_session_render = __esm(() => {
|
|
|
4842
4869
|
description: "OpenCode AGENTS.md plus opencode.json instructions pointing at managed fragments.",
|
|
4843
4870
|
providerSurface: "legacy-dual"
|
|
4844
4871
|
},
|
|
4872
|
+
sumi: {
|
|
4873
|
+
tool: "sumi",
|
|
4874
|
+
mode: "flattened-markdown",
|
|
4875
|
+
indexFile: "AGENTS.md",
|
|
4876
|
+
managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
|
|
4877
|
+
envVar: "SUMI_CONFIG_DIR",
|
|
4878
|
+
nativeImports: false,
|
|
4879
|
+
description: "Sumi native AGENTS.md in the explicit resolved config directory or project root."
|
|
4880
|
+
},
|
|
4845
4881
|
aicopilot: {
|
|
4846
4882
|
tool: "aicopilot",
|
|
4847
4883
|
mode: "flattened-markdown",
|
|
@@ -5063,6 +5099,7 @@ var init_instruction_graph = __esm(() => {
|
|
|
5063
5099
|
init_types();
|
|
5064
5100
|
init_session_render();
|
|
5065
5101
|
init_asset_plan();
|
|
5102
|
+
init_transforms();
|
|
5066
5103
|
COMMON_FALLBACKS = ["fail", "flatten", "promote-always", "omit"];
|
|
5067
5104
|
DEFAULT_PROVIDER_CAPABILITIES = Object.freeze({
|
|
5068
5105
|
claude: capability("claude", ">=1.0.0", "native-import", "CLAUDE.md @ imports plus path-gated rules", {
|
|
@@ -5074,6 +5111,7 @@ var init_instruction_graph = __esm(() => {
|
|
|
5074
5111
|
codex: capability("codex", ">=0.1.0", "flattened", "AGENTS.md", { asset_surface: "cli" }),
|
|
5075
5112
|
cursor: capability("cursor", ">=1.0.0", "cursor-rule", ".cursor/rules/*.mdc", { activation_modes: ["always", "glob"], conditional_artifacts: true, asset_surface: "ide" }),
|
|
5076
5113
|
opencode: capability("opencode", ">=1.0.0", "managed-fragment", "opencode.json instructions", { provider_variant: "v1-instructions", session_surface: "opencode-config-instructions" }),
|
|
5114
|
+
sumi: capability("sumi", ">=0.2.22 <0.3.0", "flattened", "AGENTS.md"),
|
|
5077
5115
|
codewith: capability("codewith", ">=0.1.0", "flattened", "CODEWITH.md"),
|
|
5078
5116
|
qwen: capability("qwen", ">=0.1.0", "flattened", "QWEN.md"),
|
|
5079
5117
|
aicopilot: capability("aicopilot", ">=0.1.0", "flattened", "AICOPILOT.md"),
|
|
@@ -8013,6 +8051,10 @@ function configFilterSql(filter) {
|
|
|
8013
8051
|
const parameter = `$${params.length}`;
|
|
8014
8052
|
conditions.push(`(name ILIKE ${parameter} OR description ILIKE ${parameter} OR content ILIKE ${parameter})`);
|
|
8015
8053
|
}
|
|
8054
|
+
if (filter.tags?.length) {
|
|
8055
|
+
for (const tag of filter.tags)
|
|
8056
|
+
add("tags @> $?::jsonb", JSON.stringify([tag]));
|
|
8057
|
+
}
|
|
8016
8058
|
return {
|
|
8017
8059
|
where: conditions.length ? `WHERE ${conditions.join(" AND ")}` : "",
|
|
8018
8060
|
params
|
|
@@ -8025,6 +8067,31 @@ async function listConfigsPage(client, filter = {}, options = {}) {
|
|
|
8025
8067
|
const rows = await client.many(`SELECT * FROM configs ${where} ORDER BY id LIMIT $${params.length + 1} OFFSET $${params.length + 2}`, [...params, normalized.limit, normalized.cursor]);
|
|
8026
8068
|
return boundedReadPage(rows.map(rowToConfig), Number(count?.total ?? 0), normalized);
|
|
8027
8069
|
}
|
|
8070
|
+
async function listConfigSummariesPage(client, filter = {}, options = {}) {
|
|
8071
|
+
const normalized = normalizeBoundedReadOptions(options);
|
|
8072
|
+
const { where, params } = configFilterSql(filter);
|
|
8073
|
+
const count = await client.get(`SELECT COUNT(*) AS total FROM configs ${where}`, params);
|
|
8074
|
+
const rows = await client.many(`SELECT id, name, slug, kind, category, agent, target_path, format,
|
|
8075
|
+
jsonb_array_length(outputs) AS output_count, description, tags,
|
|
8076
|
+
is_template, version, updated_at
|
|
8077
|
+
FROM configs ${where} ORDER BY id LIMIT $${params.length + 1} OFFSET $${params.length + 2}`, [...params, normalized.limit, normalized.cursor]);
|
|
8078
|
+
return boundedReadPage(rows.map((row) => ({
|
|
8079
|
+
id: row.id,
|
|
8080
|
+
slug: row.slug,
|
|
8081
|
+
name: row.name,
|
|
8082
|
+
category: row.category,
|
|
8083
|
+
agent: row.agent,
|
|
8084
|
+
kind: row.kind,
|
|
8085
|
+
format: row.format,
|
|
8086
|
+
target_path: row.target_path,
|
|
8087
|
+
output_count: Number(row.output_count ?? 0),
|
|
8088
|
+
version: row.version,
|
|
8089
|
+
is_template: Boolean(row.is_template),
|
|
8090
|
+
updated_at: toIso2(row.updated_at),
|
|
8091
|
+
description: row.description,
|
|
8092
|
+
tags: Array.isArray(row.tags) ? row.tags.map(String) : []
|
|
8093
|
+
})), Number(count?.total ?? 0), normalized);
|
|
8094
|
+
}
|
|
8028
8095
|
async function listConfigIdentitiesPage(client, filterOrOptions = {}, maybeOptions) {
|
|
8029
8096
|
const filterKeys = ["category", "agent", "kind", "is_template", "search", "tags"];
|
|
8030
8097
|
const isFilterOnly = maybeOptions === undefined && filterKeys.some((key) => (key in filterOrOptions));
|
|
@@ -8082,6 +8149,7 @@ async function createConfig(client, input) {
|
|
|
8082
8149
|
return getConfig(client, id);
|
|
8083
8150
|
}
|
|
8084
8151
|
async function updateConfig(client, idOrSlug, input) {
|
|
8152
|
+
validateExpectedConfigVersion(input.expected_version);
|
|
8085
8153
|
const existing = await getConfig(client, idOrSlug);
|
|
8086
8154
|
const sets = ["updated_at = now()", "version = version + 1"];
|
|
8087
8155
|
const params = [];
|
|
@@ -8119,13 +8187,27 @@ async function updateConfig(client, idOrSlug, input) {
|
|
|
8119
8187
|
const configIdParam = params.length;
|
|
8120
8188
|
params.push(randomUUID());
|
|
8121
8189
|
const snapshotIdParam = params.length;
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8190
|
+
let condition = "";
|
|
8191
|
+
if (input.expected_version !== undefined) {
|
|
8192
|
+
params.push(input.expected_version);
|
|
8193
|
+
condition = ` AND version::bigint = $${params.length}::bigint`;
|
|
8194
|
+
}
|
|
8195
|
+
const updated = await client.get(`WITH updated_config AS (
|
|
8196
|
+
UPDATE configs SET ${sets.join(", ")} WHERE id = $${configIdParam}${condition}
|
|
8197
|
+
RETURNING *
|
|
8198
|
+
), inserted_snapshot AS (
|
|
8199
|
+
INSERT INTO config_snapshots (id, config_id, content, version, created_at)
|
|
8200
|
+
SELECT $${snapshotIdParam}, id, content, version, now() FROM updated_config
|
|
8201
|
+
RETURNING config_id
|
|
8125
8202
|
)
|
|
8126
|
-
|
|
8127
|
-
|
|
8128
|
-
|
|
8203
|
+
SELECT updated_config.* FROM updated_config
|
|
8204
|
+
JOIN inserted_snapshot ON inserted_snapshot.config_id = updated_config.id`, params);
|
|
8205
|
+
if (!updated) {
|
|
8206
|
+
if (input.expected_version !== undefined)
|
|
8207
|
+
throw new ConfigVersionConflictError(existing.id, input.expected_version);
|
|
8208
|
+
throw new ConfigNotFoundError(existing.id);
|
|
8209
|
+
}
|
|
8210
|
+
return rowToConfig(updated);
|
|
8129
8211
|
}
|
|
8130
8212
|
async function deleteConfig(client, idOrSlug) {
|
|
8131
8213
|
const existing = await getConfig(client, idOrSlug);
|
|
@@ -8717,16 +8799,25 @@ async function handleV1Request(req, url, context = {}) {
|
|
|
8717
8799
|
...url.searchParams.get("category") ? { category: url.searchParams.get("category") } : {},
|
|
8718
8800
|
...url.searchParams.get("agent") ? { agent: url.searchParams.get("agent") } : {},
|
|
8719
8801
|
...url.searchParams.get("kind") ? { kind: url.searchParams.get("kind") } : {},
|
|
8720
|
-
...search ? { search } : {}
|
|
8802
|
+
...search ? { search } : {},
|
|
8803
|
+
...url.searchParams.getAll("tag").length ? { tags: url.searchParams.getAll("tag") } : {}
|
|
8721
8804
|
};
|
|
8722
8805
|
const options = {
|
|
8723
8806
|
limit: url.searchParams.get("limit") ?? undefined,
|
|
8724
8807
|
cursor: url.searchParams.get("cursor") ?? undefined
|
|
8725
8808
|
};
|
|
8726
|
-
|
|
8809
|
+
const view = url.searchParams.get("view");
|
|
8810
|
+
if (view !== null && view !== "identity" && view !== "summary") {
|
|
8811
|
+
return errorResponse(400, "unsupported config view", { code: "INVALID_CONFIG_VIEW" });
|
|
8812
|
+
}
|
|
8813
|
+
if (view === "identity") {
|
|
8727
8814
|
const page2 = await listConfigIdentitiesPage(client, filter, options);
|
|
8728
8815
|
return json(pagePayload("configs", page2));
|
|
8729
8816
|
}
|
|
8817
|
+
if (view === "summary") {
|
|
8818
|
+
const page2 = await listConfigSummariesPage(client, filter, options);
|
|
8819
|
+
return json({ ...page2, count: page2.items.length });
|
|
8820
|
+
}
|
|
8730
8821
|
const page = await listConfigsPage(client, filter, options);
|
|
8731
8822
|
return json(pagePayload("configs", page));
|
|
8732
8823
|
}
|
|
@@ -8772,6 +8863,18 @@ async function handleV1Request(req, url, context = {}) {
|
|
|
8772
8863
|
}
|
|
8773
8864
|
return errorResponse(405, `method ${method} not allowed on /v1/configs/:id/snapshots`);
|
|
8774
8865
|
}
|
|
8866
|
+
if (action === "conditional-update") {
|
|
8867
|
+
if (method !== "POST")
|
|
8868
|
+
return errorResponse(405, `method ${method} not allowed on /v1/configs/:id/conditional-update`);
|
|
8869
|
+
const body = await readJson(req);
|
|
8870
|
+
if (!body)
|
|
8871
|
+
return errorResponse(400, "invalid JSON body");
|
|
8872
|
+
if (body.expected_version === undefined)
|
|
8873
|
+
throw new InvalidExpectedVersionError;
|
|
8874
|
+
validateExpectedConfigVersion(body.expected_version);
|
|
8875
|
+
const config = await updateConfig(client, id, body);
|
|
8876
|
+
return json({ config });
|
|
8877
|
+
}
|
|
8775
8878
|
if (action)
|
|
8776
8879
|
return errorResponse(404, `unknown config action: ${action}`);
|
|
8777
8880
|
if (method === "GET") {
|
|
@@ -8975,6 +9078,11 @@ async function handleV1Request(req, url, context = {}) {
|
|
|
8975
9078
|
} catch (e) {
|
|
8976
9079
|
if (e instanceof HttpInputError)
|
|
8977
9080
|
return errorResponse(e.status, e.message, { code: e.code });
|
|
9081
|
+
if (e instanceof InvalidExpectedVersionError)
|
|
9082
|
+
return errorResponse(400, e.message, { code: e.code });
|
|
9083
|
+
if (e instanceof ConfigVersionConflictError) {
|
|
9084
|
+
return errorResponse(409, e.message, { code: e.code, config_id: e.config_id, expected_version: e.expected_version });
|
|
9085
|
+
}
|
|
8978
9086
|
if (e instanceof StoreValidationError)
|
|
8979
9087
|
return errorResponse(400, e.message, { code: e.code });
|
|
8980
9088
|
if (e instanceof IdempotencyConflictError)
|
|
@@ -9010,6 +9118,27 @@ var configSchema = {
|
|
|
9010
9118
|
synced_at: { type: "string", nullable: true }
|
|
9011
9119
|
}
|
|
9012
9120
|
};
|
|
9121
|
+
var configSummarySchema = {
|
|
9122
|
+
type: "object",
|
|
9123
|
+
additionalProperties: false,
|
|
9124
|
+
required: ["id", "name", "slug", "kind", "category", "agent", "target_path", "format", "output_count", "description", "tags", "is_template", "version", "updated_at"],
|
|
9125
|
+
properties: {
|
|
9126
|
+
id: { type: "string" },
|
|
9127
|
+
name: { type: "string" },
|
|
9128
|
+
slug: { type: "string" },
|
|
9129
|
+
kind: { type: "string" },
|
|
9130
|
+
category: { type: "string" },
|
|
9131
|
+
agent: { type: "string" },
|
|
9132
|
+
target_path: { type: "string", nullable: true },
|
|
9133
|
+
format: { type: "string" },
|
|
9134
|
+
output_count: { type: "number" },
|
|
9135
|
+
description: { type: "string", nullable: true },
|
|
9136
|
+
tags: { type: "array", items: { type: "string" } },
|
|
9137
|
+
is_template: { type: "boolean" },
|
|
9138
|
+
version: { type: "number" },
|
|
9139
|
+
updated_at: { type: "string" }
|
|
9140
|
+
}
|
|
9141
|
+
};
|
|
9013
9142
|
var profileSchema = {
|
|
9014
9143
|
type: "object",
|
|
9015
9144
|
properties: {
|
|
@@ -9025,6 +9154,7 @@ var profileSchema = {
|
|
|
9025
9154
|
};
|
|
9026
9155
|
var configIdentitySchema = {
|
|
9027
9156
|
type: "object",
|
|
9157
|
+
additionalProperties: false,
|
|
9028
9158
|
required: ["id", "name", "slug", "kind", "category", "agent", "format", "is_template", "version", "created_at", "updated_at", "synced_at"],
|
|
9029
9159
|
properties: {
|
|
9030
9160
|
id: { type: "string" },
|
|
@@ -9077,6 +9207,12 @@ var snapshotSchema = {
|
|
|
9077
9207
|
};
|
|
9078
9208
|
var limitParameter = { name: "limit", in: "query", schema: { type: "integer", minimum: 1, maximum: 100 } };
|
|
9079
9209
|
var cursorParameter = { name: "cursor", in: "query", schema: { type: "integer", minimum: 0, maximum: 1e5 } };
|
|
9210
|
+
var configViewParameter = {
|
|
9211
|
+
name: "view",
|
|
9212
|
+
in: "query",
|
|
9213
|
+
description: "Use summary for a content-free list projection, or identity for the smallest metadata-only projection.",
|
|
9214
|
+
schema: { type: "string", enum: ["summary", "identity"] }
|
|
9215
|
+
};
|
|
9080
9216
|
var identityViewParameter = {
|
|
9081
9217
|
name: "view",
|
|
9082
9218
|
in: "query",
|
|
@@ -9120,6 +9256,7 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
9120
9256
|
},
|
|
9121
9257
|
schemas: {
|
|
9122
9258
|
Config: configSchema,
|
|
9259
|
+
ConfigSummary: configSummarySchema,
|
|
9123
9260
|
ConfigIdentity: configIdentitySchema,
|
|
9124
9261
|
Profile: profileSchema,
|
|
9125
9262
|
ProfileIdentity: profileIdentitySchema,
|
|
@@ -9144,6 +9281,26 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
9144
9281
|
UpdateConfigInput: {
|
|
9145
9282
|
type: "object",
|
|
9146
9283
|
properties: {
|
|
9284
|
+
expected_version: { type: "integer", minimum: 1, description: "Atomically require this current version; a mismatch returns 409 without changing the config or snapshots." },
|
|
9285
|
+
name: { type: "string" },
|
|
9286
|
+
kind: { type: "string" },
|
|
9287
|
+
category: { type: "string" },
|
|
9288
|
+
agent: { type: "string" },
|
|
9289
|
+
target_path: { type: "string", nullable: true },
|
|
9290
|
+
outputs: { type: "array", items: { type: "object" } },
|
|
9291
|
+
format: { type: "string" },
|
|
9292
|
+
content: { type: "string" },
|
|
9293
|
+
description: { type: "string", nullable: true },
|
|
9294
|
+
tags: { type: "array", items: { type: "string" } },
|
|
9295
|
+
is_template: { type: "boolean" },
|
|
9296
|
+
synced_at: { type: "string", nullable: true }
|
|
9297
|
+
}
|
|
9298
|
+
},
|
|
9299
|
+
ConditionalUpdateConfigInput: {
|
|
9300
|
+
type: "object",
|
|
9301
|
+
required: ["expected_version"],
|
|
9302
|
+
properties: {
|
|
9303
|
+
expected_version: { type: "integer", minimum: 1, description: "Atomically require this current version; a mismatch returns 409 without changing the config or snapshots." },
|
|
9147
9304
|
name: { type: "string" },
|
|
9148
9305
|
kind: { type: "string" },
|
|
9149
9306
|
category: { type: "string" },
|
|
@@ -9347,6 +9504,23 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
9347
9504
|
source_bounded: { type: "boolean" }
|
|
9348
9505
|
}
|
|
9349
9506
|
},
|
|
9507
|
+
BoundedConfigSummaryPage: {
|
|
9508
|
+
type: "object",
|
|
9509
|
+
required: ["items", "total", "limit", "cursor", "next_cursor", "has_more", "complete", "truncated", "source_bounded"],
|
|
9510
|
+
properties: {
|
|
9511
|
+
configs: { type: "array", items: { $ref: "#/components/schemas/ConfigSummary" } },
|
|
9512
|
+
items: { type: "array", items: { $ref: "#/components/schemas/ConfigSummary" } },
|
|
9513
|
+
count: { type: "number" },
|
|
9514
|
+
total: { type: "number" },
|
|
9515
|
+
limit: { type: "number" },
|
|
9516
|
+
cursor: { type: "number" },
|
|
9517
|
+
next_cursor: { type: "number", nullable: true },
|
|
9518
|
+
has_more: { type: "boolean" },
|
|
9519
|
+
complete: { type: "boolean" },
|
|
9520
|
+
truncated: { type: "boolean", const: false },
|
|
9521
|
+
source_bounded: { type: "boolean" }
|
|
9522
|
+
}
|
|
9523
|
+
},
|
|
9350
9524
|
BoundedConfigIdentityPage: {
|
|
9351
9525
|
type: "object",
|
|
9352
9526
|
required: ["items", "total", "limit", "cursor", "next_cursor", "has_more", "complete", "truncated", "source_bounded"],
|
|
@@ -9485,15 +9659,17 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
9485
9659
|
{ name: "search", in: "query", schema: { type: "string", maxLength: 512 } },
|
|
9486
9660
|
limitParameter,
|
|
9487
9661
|
cursorParameter,
|
|
9488
|
-
|
|
9662
|
+
{ name: "tag", in: "query", schema: { type: "array", items: { type: "string" } } },
|
|
9663
|
+
configViewParameter
|
|
9489
9664
|
],
|
|
9490
9665
|
responses: {
|
|
9491
9666
|
"200": {
|
|
9492
9667
|
content: {
|
|
9493
9668
|
"application/json": {
|
|
9494
9669
|
schema: {
|
|
9495
|
-
|
|
9670
|
+
anyOf: [
|
|
9496
9671
|
{ $ref: "#/components/schemas/BoundedConfigPage" },
|
|
9672
|
+
{ $ref: "#/components/schemas/BoundedConfigSummaryPage" },
|
|
9497
9673
|
{ $ref: "#/components/schemas/BoundedConfigIdentityPage" }
|
|
9498
9674
|
]
|
|
9499
9675
|
}
|
|
@@ -9546,6 +9722,8 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
9546
9722
|
content: { "application/json": { schema: { $ref: "#/components/schemas/UpdateConfigInput" } } }
|
|
9547
9723
|
},
|
|
9548
9724
|
responses: {
|
|
9725
|
+
"400": { description: "Invalid expected_version; must be a positive safe integer." },
|
|
9726
|
+
"409": { description: "CONFIG_VERSION_CONFLICT: expected_version no longer matches; config and snapshots are unchanged." },
|
|
9549
9727
|
"200": {
|
|
9550
9728
|
content: {
|
|
9551
9729
|
"application/json": {
|
|
@@ -9564,6 +9742,8 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
9564
9742
|
content: { "application/json": { schema: { $ref: "#/components/schemas/UpdateConfigInput" } } }
|
|
9565
9743
|
},
|
|
9566
9744
|
responses: {
|
|
9745
|
+
"400": { description: "Invalid expected_version; must be a positive safe integer." },
|
|
9746
|
+
"409": { description: "CONFIG_VERSION_CONFLICT: expected_version no longer matches; config and snapshots are unchanged." },
|
|
9567
9747
|
"200": {
|
|
9568
9748
|
content: {
|
|
9569
9749
|
"application/json": {
|
|
@@ -9588,6 +9768,26 @@ function buildV1OpenApiDocument(version = getPackageVersion()) {
|
|
|
9588
9768
|
}
|
|
9589
9769
|
}
|
|
9590
9770
|
},
|
|
9771
|
+
"/v1/configs/{id}/conditional-update": {
|
|
9772
|
+
post: {
|
|
9773
|
+
operationId: "conditionalUpdateConfig",
|
|
9774
|
+
summary: "Atomically update a config only if its current version matches",
|
|
9775
|
+
description: "Requires expected_version. Older servers return 404 without changing the config. Clients must never retry through an unconditional update route.",
|
|
9776
|
+
parameters: [{ name: "id", in: "path", required: true, schema: { type: "string" } }],
|
|
9777
|
+
requestBody: {
|
|
9778
|
+
required: true,
|
|
9779
|
+
content: { "application/json": { schema: { $ref: "#/components/schemas/ConditionalUpdateConfigInput" } } }
|
|
9780
|
+
},
|
|
9781
|
+
responses: {
|
|
9782
|
+
"200": {
|
|
9783
|
+
content: { "application/json": { schema: { type: "object", properties: { config: { $ref: "#/components/schemas/Config" } } } } }
|
|
9784
|
+
},
|
|
9785
|
+
"400": { description: "expected_version is required and must be a positive safe integer." },
|
|
9786
|
+
"404": { description: "Config not found, or conditional updates are unsupported by this server." },
|
|
9787
|
+
"409": { description: "CONFIG_VERSION_CONFLICT: config and snapshots are unchanged." }
|
|
9788
|
+
}
|
|
9789
|
+
}
|
|
9790
|
+
},
|
|
9591
9791
|
"/v1/configs/{id}/snapshots": {
|
|
9592
9792
|
get: {
|
|
9593
9793
|
operationId: "listSnapshots",
|
|
@@ -10034,14 +10234,14 @@ app.all("/v1/*", async (c) => {
|
|
|
10034
10234
|
});
|
|
10035
10235
|
var HOST = process.env["HOST"] ?? process.env["INSTRUCTIONS_HOST"] ?? "localhost";
|
|
10036
10236
|
var serverOptions = { port: PORT, hostname: HOST, fetch: app.fetch };
|
|
10237
|
+
var server;
|
|
10037
10238
|
if (import.meta.main) {
|
|
10038
10239
|
console.log(`instructions-serve listening on http://${HOST}:${PORT} (backend: ${serviceBackend()})`);
|
|
10039
|
-
Bun.serve(serverOptions);
|
|
10240
|
+
server = Bun.serve(serverOptions);
|
|
10040
10241
|
}
|
|
10041
|
-
var server_default = app;
|
|
10042
10242
|
export {
|
|
10043
10243
|
serviceBackend,
|
|
10044
10244
|
serverOptions,
|
|
10045
|
-
|
|
10245
|
+
server,
|
|
10046
10246
|
app
|
|
10047
10247
|
};
|