@vincemakes/kiso-task-ext 0.1.45
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/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/kiso-task.mjs +130 -0
- package/index.d.ts +11 -0
- package/package.json +31 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kiso contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# kiso-task-ext
|
|
2
|
+
|
|
3
|
+
The kiso official task extension: long-horizon working memory (`task_set`),
|
|
4
|
+
the kernel untouched. Stateless — the list's memory is the session event
|
|
5
|
+
log, so it survives kill -9 and compaction.
|
|
6
|
+
|
|
7
|
+
## How it is loaded
|
|
8
|
+
|
|
9
|
+
Since 0.1.45 this extension ships **built-in** with the kiso CLI — a fresh
|
|
10
|
+
install starts with it registered (the startup banner lists it), with zero
|
|
11
|
+
disk setup. The same artifact can also be installed as a user-level
|
|
12
|
+
extension: copy `dist/kiso-task.mjs` into `~/.kiso/extensions/` — the
|
|
13
|
+
user-layer loader accepts exactly this shape.
|
|
14
|
+
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
None. No persistent resources.
|
|
18
|
+
|
|
19
|
+
## Versioning
|
|
20
|
+
|
|
21
|
+
The version counter is this package's own. It is pinned exactly by the kiso
|
|
22
|
+
CLI it ships with; an extension release reaches CLI users through the next
|
|
23
|
+
CLI release.
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kiso (foundation) official task extension — ⑥: long-horizon working memory,
|
|
3
|
+
* kernel untouched.
|
|
4
|
+
*
|
|
5
|
+
* task_set is a WHOLE-TABLE REPLACE (the CC whole-table-replace shape): the model
|
|
6
|
+
* sends the complete current list on every update — one item marked
|
|
7
|
+
* active/done, the rest carried over verbatim. Idempotent: the same items
|
|
8
|
+
* in → the same echo out, byte for byte.
|
|
9
|
+
*
|
|
10
|
+
* The extension is STATELESS — the list's memory is the SESSION EVENT LOG.
|
|
11
|
+
* The result (the normalized echo) is a durable tool-result message: it
|
|
12
|
+
* survives kill -9 (a resume rebuilds the projection from the log) and
|
|
13
|
+
* /compact (the result is tagged do-not-compact, so the summary layer's
|
|
14
|
+
* boundary never covers its round — the contrast with Claude Code's
|
|
15
|
+
* runtime-state checklist, which dies with the process).
|
|
16
|
+
*
|
|
17
|
+
* The content contract (the CLI's checklist cell parses this EXACT shape
|
|
18
|
+
* — keep it stable):
|
|
19
|
+
* [task] 3 items — 1 pending, 1 active, 1 done
|
|
20
|
+
* [pending] write the plan
|
|
21
|
+
* [active] implement the feature
|
|
22
|
+
* [done] verify with tests
|
|
23
|
+
* The first line is a count summary; every item line is
|
|
24
|
+
* `[<status>] <text>`. Unknown lines never appear — the echo is the
|
|
25
|
+
* canonical form.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
const MAX_ITEMS = 50;
|
|
29
|
+
const MAX_TEXT = 500;
|
|
30
|
+
const STATUSES = ["pending", "active", "done"];
|
|
31
|
+
|
|
32
|
+
/** Parse + validate ONE call. Pure: same input, same echo. */
|
|
33
|
+
export function parseTaskSet(input) {
|
|
34
|
+
const raw = (input ?? {}).items;
|
|
35
|
+
if (!Array.isArray(raw)) {
|
|
36
|
+
return { error: "task_set: 'items' must be an array of {text, status}" };
|
|
37
|
+
}
|
|
38
|
+
if (raw.length > MAX_ITEMS) {
|
|
39
|
+
return { error: `task_set: at most ${MAX_ITEMS} items (got ${raw.length})` };
|
|
40
|
+
}
|
|
41
|
+
const items = [];
|
|
42
|
+
for (let i = 0; i < raw.length; i += 1) {
|
|
43
|
+
const item = raw[i];
|
|
44
|
+
if (typeof item !== "object" || item === null) {
|
|
45
|
+
return { error: `task_set: item ${i} is not an object` };
|
|
46
|
+
}
|
|
47
|
+
const status = item.status;
|
|
48
|
+
if (!STATUSES.includes(status)) {
|
|
49
|
+
return { error: `task_set: item ${i} status must be one of ${STATUSES.join("/")} (got "${String(status)}")` };
|
|
50
|
+
}
|
|
51
|
+
const text = typeof item.text === "string" ? item.text.trim() : "";
|
|
52
|
+
if (text === "") {
|
|
53
|
+
return { error: `task_set: item ${i} text must be a non-empty string` };
|
|
54
|
+
}
|
|
55
|
+
if (text.length > MAX_TEXT) {
|
|
56
|
+
return { error: `task_set: item ${i} text exceeds ${MAX_TEXT} chars (got ${text.length})` };
|
|
57
|
+
}
|
|
58
|
+
items.push({ text, status });
|
|
59
|
+
}
|
|
60
|
+
// CC's discipline: at most ONE active item — a second active means the
|
|
61
|
+
// model did not mark the previous step done. Refused loudly, never
|
|
62
|
+
// silently normalized.
|
|
63
|
+
const active = items.filter((it) => it.status === "active");
|
|
64
|
+
if (active.length > 1) {
|
|
65
|
+
return { error: `task_set: at most one active item (${active.length} are active — mark the others done first)` };
|
|
66
|
+
}
|
|
67
|
+
return { items };
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** The normalized echo — the deterministic, parseable canonical form. */
|
|
71
|
+
export function taskEcho(items) {
|
|
72
|
+
const counts = { pending: 0, active: 0, done: 0 };
|
|
73
|
+
for (const it of items) counts[it.status] += 1;
|
|
74
|
+
const lines = [
|
|
75
|
+
`[task] ${items.length} item${items.length === 1 ? "" : "s"} — ${counts.pending} pending, ${counts.active} active, ${counts.done} done`,
|
|
76
|
+
...items.map((it) => `[${it.status}] ${it.text}`),
|
|
77
|
+
];
|
|
78
|
+
return lines.join("\n");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export default function createTaskExtension() {
|
|
82
|
+
return {
|
|
83
|
+
name: "task",
|
|
84
|
+
tools: [
|
|
85
|
+
{
|
|
86
|
+
name: "task_set",
|
|
87
|
+
description:
|
|
88
|
+
"set the work plan as a whole-table replace: pass the COMPLETE current list (each item {text, status}) — at most one active. The result echoes the normalized list; it survives /compact and kill -9 (durable working memory).",
|
|
89
|
+
parameters: {
|
|
90
|
+
type: "object",
|
|
91
|
+
properties: {
|
|
92
|
+
items: {
|
|
93
|
+
type: "array",
|
|
94
|
+
items: {
|
|
95
|
+
type: "object",
|
|
96
|
+
properties: {
|
|
97
|
+
text: { type: "string", minLength: 1, maxLength: MAX_TEXT },
|
|
98
|
+
status: { type: "string", enum: STATUSES },
|
|
99
|
+
},
|
|
100
|
+
required: ["text", "status"],
|
|
101
|
+
},
|
|
102
|
+
maxItems: MAX_ITEMS,
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
required: ["items"],
|
|
106
|
+
},
|
|
107
|
+
execute: async (input) => {
|
|
108
|
+
const parsed = parseTaskSet(input);
|
|
109
|
+
if (parsed.error !== undefined) {
|
|
110
|
+
return { content: parsed.error, isError: true, errorKind: "invalid_input" };
|
|
111
|
+
}
|
|
112
|
+
return { content: taskEcho(parsed.items), isError: false, tags: ["do-not-compact"] };
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
// The plan guidance — restrained, no runtime checks (a verification
|
|
117
|
+
// step is a discipline, not a gate).
|
|
118
|
+
systemPrompt: {
|
|
119
|
+
append: [
|
|
120
|
+
"Work planning (task_set):",
|
|
121
|
+
"- For a task with 3+ steps, call task_set once up front with one item",
|
|
122
|
+
" per step, and make the LAST item a verification step.",
|
|
123
|
+
"- Mark an item active just before you start it — at most one active.",
|
|
124
|
+
"- Mark an item done the moment its step completes, then call",
|
|
125
|
+
" task_set again with the whole updated list.",
|
|
126
|
+
"- For a single small step, skip the list and do the work directly.",
|
|
127
|
+
].join("\n"),
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The published type surface of @vincemakes/kiso-task-ext: the default
|
|
3
|
+
* export is the FACTORY (the same contract the user-layer disk loader
|
|
4
|
+
* accepts — a KisoExtension or a factory returning one). The type import
|
|
5
|
+
* from kiso-core is compile-time only — the shipped bundle is
|
|
6
|
+
* self-contained, zero runtime dependencies.
|
|
7
|
+
*/
|
|
8
|
+
import type { KisoExtension } from "@vincemakes/kiso-core";
|
|
9
|
+
|
|
10
|
+
declare const createTaskExtension: () => KisoExtension | Promise<KisoExtension>;
|
|
11
|
+
export default createTaskExtension;
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vincemakes/kiso-task-ext",
|
|
3
|
+
"version": "0.1.45",
|
|
4
|
+
"description": "kiso official task extension \u2014 long-horizon working memory (task_set), kernel untouched",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./dist/kiso-task.mjs",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./index.d.ts",
|
|
11
|
+
"import": "./dist/kiso-task.mjs"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"index.d.ts",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "node build.mjs",
|
|
22
|
+
"typecheck": "tsc -p tsconfig.json",
|
|
23
|
+
"test": "vitest run"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@vincemakes/kiso-core": "0.1.35",
|
|
27
|
+
"@types/node": "^26.1.2",
|
|
28
|
+
"typescript": "^5.7.2",
|
|
29
|
+
"vitest": "^3.0.0"
|
|
30
|
+
}
|
|
31
|
+
}
|